cwl_utils-0.41/.coveragerc0000644000000000000000000000031613615410400012504 0ustar00[run] branch = True source = cwl_utils [report] exclude_lines = if self.debug: pragma: no cover raise NotImplementedError if __name__ == .__main__.: ignore_errors = True omit = tests/* cwl_utils-0.41/.flake80000644000000000000000000000033413615410400011536 0ustar00[flake8] max-line-length = 100 select = B,C,E,F,W,T4 exclude = cwltool/schemas extend-ignore = E203,E501,E704,B905,W503 # when Python 3.10 is the minimum version, re-enable check B905 for zip + strict extend-select = B9 cwl_utils-0.41/CONTRIBUTING.md0000644000000000000000000000304313615410400012614 0ustar00Style guide: - PEP-8 / format with ``black`` via ``make format`` - Python 3.10+ compatible code - PEP-484 type hints It is suggested that you run `git config blame.ignoreRevsFile .git-blame-ignore-revs` to filter out mass-formatting commits from `git blame`. In order to contribute to the development of ``cwl-utils``, you need to install cwl-utils from source (preferably in a virtual environment): Here's a rough guide (improvements are welcome!) - Install virtualenv via pip: ``pip install virtualenv`` - Clone the cwl-utils Git repository: ``git clone https://github.com/common-workflow-language/cwl-utils.git`` - Switch to cwl-utils directory: ``cd cwl-utils`` - Create a virtual environment: ``virtualenv env`` - To begin using the virtual environment, it needs to be activated: ``source env/bin/activate`` - To check if you have the virtual environment set up: ``which python`` and it should point to python executable in your virtual env - Install cwl-utils in the virtual environment: ``pip install -e .`` - Check the version which might be different from the version installed in general on any system: ``pip show cwl-utils`` - After you've made the changes, you can the complete test suite via tox: ``tox`` - If you want to run specific tests, say ``unit tests`` in Python 3.13, then: ``tox -e py313-unit``. - Look at ``tox -l`` for all available tests and runtimes - If tests are passing, you can create a PR on ``cwl-utils`` GitHub repository. - After you're done working on the ``cwl-utils``, you can deactivate the virtual environment: ``deactivate`` cwl_utils-0.41/Makefile0000644000000000000000000001526413615410400012033 0ustar00# This file is part of cwl-utils, # https://github.com/common-workflow-language/cwl-utils/, and is # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # Contact: common-workflow-language@googlegroups.com # make format to fix most python formatting errors # make pylint to check Python code for enhanced compliance including naming # and documentation # make coverage-report to check coverage of the python scripts by the tests MODULE=cwl_utils PACKAGE=cwl-utils EXTRAS="[testing]" # `SHELL=bash` doesn't work for some, so don't use BASH-isms like # `[[` conditional expressions. PYSOURCES=$(filter-out $(MODULE)/parser/cwl_v%,$(shell find $(MODULE) -name "*.py")) \ create_cwl_from_objects.py load_cwl_by_path.py \ ${MODULE}/parser/cwl_v1_?_utils.py docs/conf.py DEVPKGS=build diff_cover pylint pep257 ruff 'tox>=4' \ wheel autoflake pyupgrade bandit auto-walrus \ -rlint-requirements.txt -rmypy-requirements.txt DEBDEVPKGS=pep8 python-autopep8 pylint python-coverage ruff sloccount \ python-flake8 python-mock shellcheck VERSION=v$(shell echo $$(tail -n 1 cwl_utils/__meta__.py | awk '{print $$3}')) mkfile_dir := $(dir $(abspath $(lastword $(MAKEFILE_LIST)))) UNAME_S=$(shell uname -s) ## all : default task (install cwl-utils in dev mode) all: dev ## help : print this help message and exit help: Makefile @sed -n 's/^##//p' $< ## cleanup : shortcut for "make sort_imports format flake8 pydocstyle" cleanup: sort_imports format flake8 pydocstyle ## install-dep : install most of the development dependencies via pip install-dep: install-dependencies install-dependencies: pip install -U pip wheel build pip install --upgrade $(DEVPKGS) ## install-deb-dep : install many of the dev dependencies via apt-get install-deb-dep: sudo apt-get install $(DEBDEVPKGS) ## install : install the cwl-utils package and the scripts install: FORCE pip install .$(EXTRAS) ## dev : install the cwl-utils package in dev mode dev: install-dep pip install -U pip wheel pip install -e .$(EXTRAS) ## dist : create a module package for distribution dist: dist/${MODULE}-$(VERSION).tar.gz dist/${MODULE}-$(VERSION).tar.gz: $(SOURCES) python3 -m build ## docs : make the docs docs: FORCE cd docs && $(MAKE) html ## clean : clean up all temporary / machine-generated files clean: FORCE rm -f ${MODULE}/*.pyc ${MODULE}/tests/*.pyc rm -Rf .coverage rm -f diff-cover.html # Linting and code style related targets ## sort_import : sorting imports using isort: https://github.com/timothycrosley/isort sort_imports: FORCE isort $(PYSOURCES) remove_unused_imports: FORCE autoflake --in-place --remove-all-unused-imports $(PYSOURCES) pep257: pydocstyle ## pydocstyle : check Python docstring style pydocstyle: FORCE ruff check $(PYSOURCES) ## codespell : check for common misspellings codespell: FORCE codespell -w $(shell git ls-files | grep -v mypy-stubs) ## format : check/fix all code indentation and formatting (runs black) format: FORCE black $(PYSOURCES) format-check: FORCE black --diff --check $(PYSOURCES) ## pylint : run static code analysis on Python code pylint: FORCE pylint --msg-template="{path}:{line}: [{msg_id}({symbol}), {obj}] {msg}" \ $(PYSOURCES) -j0|| true pylint_report.txt: FORCE pylint --msg-template="{path}:{line}: [{msg_id}({symbol}), {obj}] {msg}" \ $(PYSOURCES) -j0> $@ || true diff_pylint_report: pylint_report.txt diff-quality --compare-branch=main --violations=pylint pylint_report.txt .coverage: testcov coverage: .coverage coverage report coverage.xml: .coverage coverage xml coverage.html: htmlcov/index.html htmlcov/index.html: .coverage coverage html @echo Test coverage of the Python code is now in htmlcov/index.html coverage-report: .coverage coverage report diff-cover: coverage.xml diff-cover --compare-branch=main $^ diff-cover.html: coverage.xml diff-cover --compare-branch=main $^ --html-report $@ ## test : run the cwl-utils test suite test: FORCE python3 -m pytest ${PYTEST_EXTRA} ## testcov : run the cwl-utils test suite and collect coverage testcov: FORCE python3 -m pytest --cov ${PYTEST_EXTRA} sloccount.sc: FORCE sloccount --duplicates --wide --details $(PYSOURCES) Makefile > $@ ## sloccount : count lines of code sloccount: FORCE sloccount $(PYSOURCES) Makefile list-author-emails: @echo 'name, E-Mail Address' @git log --format='%aN,%aE' | sort -u | grep -v 'root' mypy: FORCE MYPYPATH=$$MYPYPATH:mypy-stubs mypy $(PYSOURCES) mypyc: FORCE MYPYPATH=mypy-stubs HATCH_BUILD_HOOKS_ENABLE=1 pip install --verbose -e . \ && pytest "${PYTEST_EXTRA}" shellcheck: FORCE shellcheck release-test.sh pyupgrade: FORCE pyupgrade --exit-zero-even-if-changed --py310-plus $(PYSOURCES) auto-walrus $(PYSOURCES) release-test: FORCE git diff-index --quiet HEAD -- || ( echo You have uncommitted changes, please commit them and try again; false ) ./release-test.sh release: release-test . testenv2/bin/activate && \ pip install build && \ python3 -m build testenv2/src/${PACKAGE} && \ pip install twine && \ twine upload testenv2/src/${PACKAGE}/dist/* && \ git tag ${VERSION} && git push --tags flake8: FORCE flake8 $(PYSOURCES) cwl_utils/parser/cwl_v1_0.py: FORCE schema-salad-tool --codegen python \ --codegen-parser-info "org.w3id.cwl.v1_0" \ https://github.com/common-workflow-language/common-workflow-language/raw/codegen/v1.0/extensions.yml \ > $@ cwl_utils/parser/cwl_v1_1.py: FORCE schema-salad-tool --codegen python \ --codegen-parser-info "org.w3id.cwl.v1_1" \ https://github.com/common-workflow-language/cwl-v1.1/raw/codegen/extensions.yml \ > $@ cwl_utils/parser/cwl_v1_2.py: FORCE schema-salad-tool --codegen python \ --codegen-parser-info "org.w3id.cwl.v1_2" \ https://github.com/common-workflow-language/cwl-v1.2/raw/codegen/extensions.yml \ > $@ regen_parsers: cwl_utils/parser/cwl_v1_*.py FORCE: # Use this to print the value of a Makefile variable # Example `make print-VERSION` # From https://www.cmcrossroads.com/article/printing-value-makefile-variable print-% : ; @echo $* = $($*) cwl_utils-0.41/create_cwl_from_objects.py0000755000000000000000000000142613615410400015607 0ustar00#!/usr/bin/env python3 # SPDX-License-Identifier: Apache-2.0 import sys import ruamel.yaml from cwl_utils.parser import cwl_v1_2 as cwl def main() -> None: """Generate a CWL object to match "cat-tool.cwl".""" inputs = [cwl.CommandInputParameter(id="file1", type_="File")] outputs = [ cwl.CommandOutputParameter( id="output", type_="File", outputBinding=cwl.CommandOutputBinding(glob="output"), ) ] cat_tool = cwl.CommandLineTool( inputs=inputs, outputs=outputs, cwlVersion="v1.2", baseCommand="cat", stdin="$(inputs.file1.path)", stdout="output", ) yaml = ruamel.yaml.YAML() yaml.dump(cat_tool.save(), sys.stdout) if __name__ == "__main__": main() cwl_utils-0.41/cwl_utils/__init__.py0000644000000000000000000000017613615410400014505 0ustar00# SPDX-License-Identifier: Apache-2.0 """Python Utilities and Autogenerated Classes for loading and parsing CWL documents.""" cwl_utils-0.41/cwl_utils/__meta__.py0000644000000000000000000000016313615410400014464 0ustar00# SPDX-License-Identifier: Apache-2.0 """Global version number for the cwl_utils package.""" __version__ = "0.41" cwl_utils-0.41/cwl_utils/cite_extract.py0000755000000000000000000000514713615410400015432 0ustar00#!/usr/bin/env python3 # SPDX-License-Identifier: Apache-2.0 import argparse import sys from collections.abc import Iterator from typing import cast import cwl_utils.parser as cwl def arg_parser() -> argparse.ArgumentParser: """Construct the argument parser.""" parser = argparse.ArgumentParser( description="Print information about software used in a CWL document (Workflow or CommandLineTool). " "For CWL Workflows, all steps will also be searched (recursively)." ) parser.add_argument( "input", help="Input CWL document (CWL Workflow or CWL CommandLineTool)" ) return parser def run(args: argparse.Namespace) -> int: """Extract the software requirements.""" for req in traverse(cwl.load_document_by_uri(args.input)): process_software_requirement(req) return 0 def main() -> int: """Console entry point.""" return run(arg_parser().parse_args(sys.argv[1:])) def extract_software_reqs( process: cwl.Process, ) -> Iterator[cwl.SoftwareRequirement]: """Return an iterator over any SoftwareRequirements found in the given process.""" if process.requirements: for req in process.requirements: if isinstance(req, cwl.SoftwareRequirementTypes): yield req if process.hints: for req in process.hints: if isinstance(req, cwl.SoftwareRequirementTypes): yield req def process_software_requirement(req: cwl.SoftwareRequirement) -> None: """Pretty print the software package information.""" for package in req.packages: print( "Package: {}, version: {}, specs: {}".format( package.package, package.version, package.specs ) ) def traverse(process: cwl.Process) -> Iterator[cwl.SoftwareRequirement]: """Extract the software packages for this process, and any steps.""" yield from extract_software_reqs(process) if isinstance(process, cwl.WorkflowTypes): yield from traverse_workflow(process) def get_process_from_step(step: cwl.WorkflowStep) -> cwl.Process: """Return the process for this step, loading it if needed.""" if isinstance(step.run, str): return cast(cwl.Process, cwl.load_document_by_uri(step.run)) return cast(cwl.Process, step.run) def traverse_workflow(workflow: cwl.Workflow) -> Iterator[cwl.SoftwareRequirement]: """Iterate over the given workflow, extracting the software packages.""" for step in workflow.steps: yield from extract_software_reqs(step) yield from traverse(get_process_from_step(step)) if __name__ == "__main__": sys.exit(main()) cwl_utils-0.41/cwl_utils/cwlNodeEngine.js0000755000000000000000000000113313615410400015450 0ustar00"use strict"; process.stdin.setEncoding("utf8"); var incoming = ""; process.stdin.on("data", function(chunk) { incoming += chunk; var i = incoming.indexOf("\n"); if (i > -1) { try{ var fn = JSON.parse(incoming.substr(0, i)); incoming = incoming.substr(i+1); process.stdout.write(JSON.stringify(require("vm").runInNewContext(fn, {})) + "\n"); } catch(e){ console.error(e) } /*strings to indicate the process has finished*/ console.log("r1cepzbhUTxtykz5XTC4"); console.error("r1cepzbhUTxtykz5XTC4"); } }); process.stdin.on("end", process.exit); cwl_utils-0.41/cwl_utils/cwlNodeEngineJSConsole.js0000644000000000000000000000173113615410400017231 0ustar00"use strict"; function js_console_log(){ console.error("[log] "+require("util").format.apply(this, arguments).split("\n").join("\n[log] ")); } function js_console_err(){ console.error("[err] "+require("util").format.apply(this, arguments).split("\n").join("\n[err] ")); } process.stdin.setEncoding("utf8"); var incoming = ""; process.stdin.on("data", function(chunk) { incoming += chunk; var i = incoming.indexOf("\n"); if (i > -1) { try{ var fn = JSON.parse(incoming.substr(0, i)); incoming = incoming.substr(i+1); process.stdout.write(JSON.stringify(require("vm").runInNewContext(fn, { console: { log: js_console_log, error: js_console_err } })) + "\n"); } catch(e){ console.error(e) } /*strings to indicate the process has finished*/ console.log("r1cepzbhUTxtykz5XTC4"); console.error("r1cepzbhUTxtykz5XTC4"); } }); process.stdin.on("end", process.exit); cwl_utils-0.41/cwl_utils/cwlNodeEngineWithContext.js0000644000000000000000000000157713615410400017662 0ustar00"use strict"; process.stdin.setEncoding("utf8"); var incoming = ""; var firstInput = true; var context = {}; process.stdin.on("data", function(chunk) { incoming += chunk; var i = incoming.indexOf("\n"); while (i > -1) { try{ var input = incoming.substr(0, i); incoming = incoming.substr(i+1); var fn = JSON.parse(input); if(firstInput){ context = require("vm").runInNewContext(fn, {}); } else{ process.stdout.write(JSON.stringify(require("vm").runInNewContext(fn, context)) + "\n"); } } catch(e){ console.error(e); } if(firstInput){ firstInput = false; } else{ /*strings to indicate the process has finished*/ console.log("r1cepzbhUTxtykz5XTC4"); console.error("r1cepzbhUTxtykz5XTC4"); } i = incoming.indexOf("\n"); } }); process.stdin.on("end", process.exit); cwl_utils-0.41/cwl_utils/cwl_v1_0_expression_refactor.py0000755000000000000000000025276413615410400020543 0ustar00#!/usr/bin/env python3 # SPDX-License-Identifier: Apache-2.0 # Copyright 2018-2021 Michael R. Crusoe """CWL Expression refactoring tool for CWL v1.0 .""" import copy import hashlib import uuid from collections.abc import MutableSequence, Sequence from contextlib import suppress from typing import Any, cast from ruamel import yaml from schema_salad.sourceline import SourceLine from schema_salad.utils import json_dumps import cwl_utils.parser.cwl_v1_0 as cwl import cwl_utils.parser.cwl_v1_0_utils as utils from cwl_utils.errors import JavascriptException, WorkflowException from cwl_utils.expression import do_eval, interpolate from cwl_utils.types import ( CWLDirectoryType, CWLFileType, CWLObjectType, CWLOutputType, CWLParameterContext, CWLRuntimeParameterContext, is_file_or_directory, ) def expand_stream_shortcuts(process: cwl.CommandLineTool) -> cwl.CommandLineTool: """Rewrite the "type: stdout" shortcut to use an explicit random filename.""" if not process.outputs: return process result = None for index, output in enumerate(process.outputs): if output.type_ == "stdout": # TODO: add 'stdin' for CWL v1.1 if not result: result = copy.deepcopy(process) stdout_path = process.stdout if not stdout_path: stdout_path = hashlib.sha1( # nosec json_dumps(cwl.save(process)).encode("utf-8") ).hexdigest() result.stdout = stdout_path result.outputs[index].type_ = "File" output.outputBinding = cwl.CommandOutputBinding(stdout_path, None, None) if result: return result return process def escape_expression_field(contents: str) -> str: """Escape sequences similar to CWL expressions or param references.""" return contents.replace("${", "$/{").replace("$(", "$/(") def clean_type_ids( cwltype: cwl.ArraySchema | cwl.InputRecordSchema, ) -> cwl.ArraySchema | cwl.InputRecordSchema: """Simplify type identifiers.""" result = copy.deepcopy(cwltype) if isinstance(result, cwl.ArraySchema): if isinstance(result.items, MutableSequence): for item in result.items: if hasattr(item, "id"): item.id = item.id.split("#")[-1] elif isinstance(result.items, cwl.InputRecordSchema): if result.items.name: result.items.name = result.items.name.split("/")[-1] if result.items.fields: for field in result.items.fields: field.name = field.name.split("/")[-1] elif isinstance(result, cwl.InputRecordSchema): if result.name: result.name = result.name.split("/")[-1] if result.fields: for field in result.fields: field.name = field.name.split("/")[-1] return result def get_expression( string: str, inputs: CWLObjectType, self: CWLOutputType | None ) -> str | None: """ Find and return a normalized CWL expression, if any. CWL expressions in the $() form are converted to the ${} form. """ if not isinstance(string, str): return None if string.strip().startswith("${"): return string if "$(" in string: runtime = CWLRuntimeParameterContext( cores=0, ram=0, outdir="/root", tmpdir="/tmp", # nosec outdirSize=0, tmpdirSize=0, ) try: do_eval( string, inputs, context=self, requirements=[], outdir="", tmpdir="", resources={}, ) except (WorkflowException, JavascriptException): if ( string[0:2] != "$(" or not string.endswith(")") or len(string.split("$(")) > 2 ): # then it is a string interpolation return cast( str, interpolate( scan=string, rootvars=CWLParameterContext( inputs=inputs, self=self, runtime=runtime ), fullJS=True, escaping_behavior=2, convert_to_expression=True, ), ) else: # it is a CWL Expression in $() with no string interpolation return "${return " + string.strip()[2:-1] + ";}" return None def etool_to_cltool( etool: cwl.ExpressionTool, expressionLib: list[str] | None = None ) -> cwl.CommandLineTool: """Convert a ExpressionTool to a CommandLineTool.""" inputs = yaml.comments.CommentedSeq() # preserve the order for inp in etool.inputs: inputs.append( cwl.CommandInputParameter( id=inp.id, label=inp.label, secondaryFiles=inp.secondaryFiles, streamable=inp.streamable, doc=inp.doc, format=inp.format, default=inp.default, type_=inp.type_, extension_fields=inp.extension_fields, loadingOptions=inp.loadingOptions, ) ) outputs = yaml.comments.CommentedSeq() for outp in etool.outputs: outputs.append( cwl.CommandOutputParameter( id=outp.id, label=outp.label, secondaryFiles=outp.secondaryFiles, streamable=outp.streamable, doc=outp.doc, format=outp.format, type_=outp.type_, extension_fields=outp.extension_fields, loadingOptions=outp.loadingOptions, ) ) contents = """"use strict"; var inputs=$(inputs); var runtime=$(runtime);""" if expressionLib: contents += "\n" + "\n".join(expressionLib) contents += ( """ var ret = function(){""" + escape_expression_field(etool.expression.strip()[2:-1]) + """}(); process.stdout.write(JSON.stringify(ret));""" ) listing = [cwl.Dirent(entryname="expression.js", entry=contents, writable=None)] iwdr = cwl.InitialWorkDirRequirement(listing) containerReq = cwl.DockerRequirement(dockerPull="node:alpine") softwareHint = cwl.SoftwareRequirement( packages=[cwl.SoftwarePackage(package="nodejs")] ) return cwl.CommandLineTool( inputs=inputs, outputs=outputs, id=etool.id, requirements=[iwdr], hints=[containerReq, softwareHint], label=etool.label, doc=etool.doc, cwlVersion=etool.cwlVersion, baseCommand=["nodejs", "expression.js"], stdout="cwl.output.json", extension_fields=etool.extension_fields, loadingOptions=etool.loadingOptions, ) def traverse( process: cwl.CommandLineTool | cwl.ExpressionTool | cwl.Workflow, replace_etool: bool, inside: bool, skip_command_line1: bool, skip_command_line2: bool, ) -> tuple[cwl.CommandLineTool | cwl.ExpressionTool | cwl.Workflow, bool]: """Convert the given process and any subprocesses.""" match process: case cwl.CommandLineTool() if not inside: process = expand_stream_shortcuts(process) wf_inputs = [] wf_outputs = [] step_inputs = [] step_outputs = [] if process.inputs: for inp in process.inputs: inp_id = inp.id.split("#")[-1] step_inputs.append( cwl.WorkflowStepInput( id=inp_id, source=inp_id, extension_fields=inp.extension_fields, loadingOptions=inp.loadingOptions, ) ) wf_inputs.append( cwl.InputParameter( id=inp_id, label=inp.label, secondaryFiles=inp.secondaryFiles, streamable=inp.streamable, doc=inp.doc, format=inp.format, default=inp.default, type_=inp.type_, extension_fields=inp.extension_fields, loadingOptions=inp.loadingOptions, ) ) if process.outputs: for outp in process.outputs: outp_id = outp.id.split("#")[-1] step_outputs.append(outp_id) wf_outputs.append( cwl.WorkflowOutputParameter( id=outp_id, label=outp.label, secondaryFiles=outp.secondaryFiles, streamable=outp.streamable, doc=outp.doc, format=outp.format, outputSource=f"main/{outp_id}", type_=outp.type_, extension_fields=outp.extension_fields, loadingOptions=outp.loadingOptions, ) ) step = cwl.WorkflowStep( id="#main", in_=step_inputs, out=step_outputs, run=copy.deepcopy(process), ) workflow = cwl.Workflow( inputs=wf_inputs, outputs=wf_outputs, steps=[step], cwlVersion=process.cwlVersion, ) result, modified = traverse_workflow( workflow, replace_etool, skip_command_line1, skip_command_line2 ) if modified: return result, True else: return process, False case cwl.ExpressionTool() if replace_etool: expression = get_expression(process.expression, empty_inputs(process), None) # Why call get_expression on an ExpressionTool? # It normalizes the form of $() CWL expressions into the ${} style if expression: process2 = copy.deepcopy(process) process2.expression = expression else: process2 = process return etool_to_cltool(process2), True case cwl.Workflow(): return traverse_workflow( process, replace_etool, skip_command_line1, skip_command_line2 ) case _: return process, False def load_step( step: cwl.WorkflowStep, replace_etool: bool, skip_command_line1: bool, skip_command_line2: bool, ) -> bool: """If the step's Process is not inline, load and process it.""" modified = False if isinstance(step.run, str): step.run, modified = traverse( cwl.load_document(step.run, baseuri=step.loadingOptions.fileuri), replace_etool, True, skip_command_line1, skip_command_line2, ) return modified def generate_etool_from_expr( expr: str, target: cwl.CommandInputParameter | cwl.InputParameter, no_inputs: bool = False, self_type: None | ( cwl.InputParameter | cwl.CommandInputParameter | list[cwl.InputParameter | cwl.CommandInputParameter] ) = None, # if the "self" input should be a different type than the "result" output extra_processes: None | ( Sequence[cwl.Workflow | cwl.WorkflowStep | cwl.CommandLineTool] ) = None, ) -> cwl.ExpressionTool: """Convert a CWL Expression into an ExpressionTool.""" inputs = yaml.comments.CommentedSeq() if not no_inputs: if not self_type: self_type = target if isinstance(self_type, list): new_type: ( list[cwl.ArraySchema | cwl.InputRecordSchema] | cwl.ArraySchema | cwl.InputRecordSchema ) = [clean_type_ids(t.type_) for t in self_type if t.type_] elif self_type.type_: new_type = clean_type_ids(self_type.type_) else: raise WorkflowException(f"Don't know how to make type from {self_type!r}.") inputs.append( cwl.InputParameter( id="self", label=self_type.label if not isinstance(self_type, list) else None, secondaryFiles=( self_type.secondaryFiles if not isinstance(self_type, list) else None ), streamable=( self_type.streamable if not isinstance(self_type, list) else None ), doc=self_type.doc if not isinstance(self_type, list) else None, format=self_type.format if not isinstance(self_type, list) else None, type_=new_type, extension_fields=( self_type.extension_fields if not isinstance(self_type, list) else None ), loadingOptions=( self_type.loadingOptions if not isinstance(self_type, list) else None ), ) ) outputs = yaml.comments.CommentedSeq() outputs.append( cwl.ExpressionToolOutputParameter( id="result", label=target.label, secondaryFiles=target.secondaryFiles, streamable=target.streamable, doc=target.doc, format=target.format, type_=target.type_, extension_fields=target.extension_fields, loadingOptions=target.loadingOptions, ) ) expression = "${" if not no_inputs: expression += "\n var self=inputs.self;" expression += ( """ return {"result": function(){""" + expr[2:-2] + """}()}; }""" ) inlineJSReq = cwl.InlineJavascriptRequirement( find_expressionLib(extra_processes) if extra_processes else None ) return cwl.ExpressionTool( id="_:" + str(uuid.uuid4()), inputs=inputs, outputs=outputs, expression=expression, requirements=[inlineJSReq], cwlVersion="v1.0", ) def get_input_for_id( name: str, tool: cwl.CommandLineTool | cwl.Workflow ) -> cwl.CommandInputParameter | None: """Determine the CommandInputParameter for the given input name.""" name = name.split("/")[-1] for inp in cast(list[cwl.CommandInputParameter], tool.inputs): if inp.id and inp.id.split("#")[-1].split("/")[-1] == name: return inp if isinstance(tool, cwl.Workflow) and "/" in name: stepname, stem = name.split("/", 1) for step in tool.steps: if step.id == stepname: result = get_input_for_id(stem, step.run) if result: return result return None def find_expressionLib( processes: Sequence[ cwl.CommandLineTool | cwl.Workflow | cwl.ExpressionTool | cwl.WorkflowStep ], ) -> list[str] | None: """ Return the expressionLib from the highest priority InlineJavascriptRequirement. processes: should be in order of least important to most important (Workflow, WorkflowStep, ... CommandLineTool/ExpressionTool) """ for process in reversed(copy.copy(processes)): if process.requirements: for req in process.requirements: if isinstance(req, cwl.InlineJavascriptRequirement): return cast(list[str] | None, copy.deepcopy(req.expressionLib)) return None def replace_expr_with_etool( expr: str, name: str, workflow: cwl.Workflow, target: cwl.CommandInputParameter | cwl.InputParameter, source: str | list[Any] | None, replace_etool: bool = False, extra_process: None | ( cwl.Workflow | cwl.WorkflowStep | cwl.CommandLineTool ) = None, source_type: cwl.CommandInputParameter | None = None, ) -> None: """Modify the given workflow, replacing the expr with an standalone ExpressionTool.""" extra_processes: list[cwl.Workflow | cwl.WorkflowStep | cwl.CommandLineTool] = [ workflow ] if extra_process: extra_processes.append(extra_process) etool: cwl.ExpressionTool = generate_etool_from_expr( expr, target, source is None, source_type, extra_processes ) if replace_etool: processes: list[cwl.WorkflowStep | cwl.Workflow | cwl.CommandLineTool] = [ workflow ] if extra_process: processes.append(extra_process) final_tool: cwl.ExpressionTool | cwl.CommandLineTool = etool_to_cltool( etool, find_expressionLib(processes) ) else: final_tool = etool inps = [] if source: inps.append(cwl.WorkflowStepInput(id="self", source=source)) workflow.steps.append( cwl.WorkflowStep( id=name, in_=inps, out=[cwl.WorkflowStepOutput("result")], run=final_tool, ) ) def replace_wf_input_ref_with_step_output( workflow: cwl.Workflow, name: str, target: str ) -> None: """Refactor all reference to a workflow input to the specified step output.""" if workflow.steps: for step in workflow.steps: if step.in_: for inp in step.in_: if inp.source: if inp.source == name: inp.source = target if isinstance(inp.source, MutableSequence): for index, source in enumerate(inp.source): if source == name: inp.source[index] = target if workflow.outputs: for outp in workflow.outputs: if outp.outputSource: if outp.outputSource == name: outp.outputSource = target if isinstance(outp.outputSource, MutableSequence): for index, outputSource in enumerate(outp.outputSource): if outputSource == name: outp.outputSource[index] = target def empty_inputs( process_or_step: ( cwl.CommandLineTool | cwl.WorkflowStep | cwl.ExpressionTool | cwl.Workflow ), parent: cwl.Workflow | None = None, ) -> dict[str, Any]: """Produce a mock input object for the given inputs.""" result = {} if isinstance(process_or_step, cwl.Process): for param in process_or_step.inputs: result[param.id.split("#")[-1]] = example_input(param.type_) else: for param in process_or_step.in_: param_id = param.id.split("/")[-1] if param.source is None and param.valueFrom: result[param_id] = example_input("string") elif param.source is None and param.default: result[param_id] = param.default else: with suppress(WorkflowException): result[param_id] = example_input( utils.type_for_source(process_or_step.run, param.source, parent) ) return result def example_input(some_type: Any) -> Any: """Produce a fake input for the given type.""" # TODO: accept some sort of context object with local custom type definitions if some_type == "Directory": return CWLDirectoryType( **{ "class": "Directory", "location": "https://www.example.com/example", "basename": "example", "listing": [ CWLFileType( **{ "class": "File", "basename": "example.txt", "size": 23, "contents": "hoopla", "nameroot": "example", "nameext": "txt", } ) ], } ) if some_type == "File": return CWLFileType( **{ "class": "File", "location": "https://www.example.com/example.txt", "basename": "example.txt", "size": 23, "contents": "hoopla", "nameroot": "example", "nameext": "txt", } ) if some_type == "int": return 23 if some_type == "string": return "hoopla!" if some_type == "boolean": return True return None EMPTY_FILE = CWLFileType( **{ "class": "File", "basename": "em.pty", "nameroot": "em", "nameext": "pty", } ) TOPLEVEL_SF_EXPR_ERROR = ( "Input '{}'. Sorry, CWL Expressions as part of a secondaryFiles " "specification in a Workflow level input or standalone CommandLine Tool " "are not able to be refactored into separate ExpressionTool or " "CommandLineTool steps." ) TOPLEVEL_FORMAT_EXPR_ERROR = ( "Input '{}'. Sorry, CWL Expressions as part of a format " "specification in a Workflow level input are not able to be refactored " "into separate ExpressionTool/CommandLineTool steps." ) def process_workflow_inputs_and_outputs( workflow: cwl.Workflow, replace_etool: bool ) -> bool: """Do any needed conversions on the given Workflow's inputs and outputs.""" modified = False inputs = empty_inputs(workflow) for index, param in enumerate(workflow.inputs): with SourceLine(workflow.inputs, index, WorkflowException): if param.format and get_expression(param.format, inputs, None): raise SourceLine( param.loadingOptions.original_doc, "format", raise_type=WorkflowException, ).makeError(TOPLEVEL_FORMAT_EXPR_ERROR.format(param.id.split("#")[-1])) if param.secondaryFiles: if get_expression(param.secondaryFiles, inputs, EMPTY_FILE): raise SourceLine( param.loadingOptions.original_doc, "secondaryFiles", raise_type=WorkflowException, ).makeError(TOPLEVEL_SF_EXPR_ERROR.format(param.id.split("#")[-1])) elif isinstance(param.secondaryFiles, MutableSequence): for index2, entry in enumerate(param.secondaryFiles): if get_expression(entry, inputs, EMPTY_FILE): raise SourceLine( param.loadingOptions.original_doc, index2, raise_type=WorkflowException, ).makeError( f"Entry {index}," + TOPLEVEL_SF_EXPR_ERROR.format(param.id.split("#")[-1]) ) return modified def process_workflow_reqs_and_hints( workflow: cwl.Workflow, replace_etool: bool ) -> bool: """ Convert any expressions in a workflow's reqs and hints. Each expression will be converted to an additional step. The converted requirement will be copied to all workflow steps that don't have that requirement type. Those affected steps will gain an additional input from the relevant synthesized expression step. """ # TODO: consolidate the generated etools/cltools into a single "_expression_workflow_reqs" step # TODO: support resourceReq.* references to Workflow.inputs? # ^ By refactoring replace_expr_etool to allow multiple inputs, # and connecting all workflow inputs to the generated step modified = False inputs = empty_inputs(workflow) generated_res_reqs: list[tuple[str, int | str]] = [] generated_iwdr_reqs: list[tuple[str, int | str]] = [] generated_envVar_reqs: list[tuple[str, int | str]] = [] prop_reqs: tuple[ ( type[cwl.EnvVarRequirement] | type[cwl.ResourceRequirement] | type[cwl.InitialWorkDirRequirement] ), ..., ] = () resourceReq: cwl.ResourceRequirement | None = None envVarReq: cwl.EnvVarRequirement | None = None iwdr: cwl.InitialWorkDirRequirement | None = None if workflow.requirements is not None: for req in cast(list[cwl.ProcessRequirement], workflow.requirements): match req: case cwl.EnvVarRequirement() if req.envDef: for index, envDef in enumerate(req.envDef): if envDef.envValue: expression = get_expression(envDef.envValue, inputs, None) if expression: modified = True target = cwl.InputParameter( id=None, type_="string", ) etool_id = ( "_expression_workflow_EnvVarRequirement_{}".format( index ) ) replace_expr_with_etool( expression, etool_id, workflow, target, None, replace_etool, ) if envVarReq is None: envVarReq = copy.deepcopy(req) prop_reqs += (cwl.EnvVarRequirement,) newEnvDef = copy.deepcopy(envDef) newEnvDef.envValue = f"$(inputs._envDef{index})" envVarReq.envDef[index] = newEnvDef generated_envVar_reqs.append((etool_id, index)) case cwl.ResourceRequirement(): for attr in cwl.ResourceRequirement.attrs: this_attr = getattr(req, attr, None) if this_attr: expression = get_expression(this_attr, inputs, None) if expression: modified = True target = cwl.InputParameter(id=None, type_="long") etool_id = "_expression_workflow_ResourceRequirement_{}".format( attr ) replace_expr_with_etool( expression, etool_id, workflow, target, None, replace_etool, ) if not resourceReq: resourceReq = cwl.ResourceRequirement( loadingOptions=workflow.loadingOptions, ) prop_reqs += (cwl.ResourceRequirement,) setattr(resourceReq, attr, f"$(inputs._{attr})") generated_res_reqs.append((etool_id, attr)) case cwl.InitialWorkDirRequirement() if req.listing: if isinstance(req.listing, str): expression = get_expression(req.listing, inputs, None) if expression: modified = True target = cwl.InputParameter( id=None, type_=cwl.InputArraySchema( ["File", "Directory"], "array", None, None ), ) etool_id = "_expression_workflow_InitialWorkDirRequirement" replace_expr_with_etool( expression, etool_id, workflow, target, None, replace_etool, ) iwdr = cwl.InitialWorkDirRequirement( listing="$(inputs._iwdr_listing)", loadingOptions=workflow.loadingOptions, ) prop_reqs += (cwl.InitialWorkDirRequirement,) else: iwdr = copy.deepcopy(req) for index, entry in enumerate(req.listing): expression = get_expression(entry, inputs, None) if expression: modified = True target = cwl.InputParameter( id=None, type_=cwl.InputArraySchema( ["File", "Directory"], "array", None, None ), ) etool_id = "_expression_workflow_InitialWorkDirRequirement_{}".format( index ) replace_expr_with_etool( expression, etool_id, workflow, target, None, replace_etool, ) iwdr.listing[index] = f"$(inputs._iwdr_listing_{index}" generated_iwdr_reqs.append((etool_id, index)) elif isinstance(entry, cwl.Dirent): if entry.entry: expression = get_expression( entry.entry, inputs, None ) if expression: expr: str = expression expr_result = do_eval( ex=entry.entry, jobinput=inputs, requirements=[], outdir="", tmpdir="", resources={}, ) modified = True if is_file_or_directory(expr_result): target = cwl.InputParameter( id=None, type_=expr_result["class"], ) replace_expr_with_etool( expr, etool_id, workflow, target, None, replace_etool, ) iwdr.listing[index] = ( "$(inputs._iwdr_listing_{}".format( index ) ) generated_iwdr_reqs.append( (etool_id, index) ) elif isinstance(expr_result, str): target = cwl.InputParameter( id=None, type_=["File"], ) if entry.entryname is None: raise SourceLine( entry.loadingOptions.original_doc, index, raise_type=WorkflowException, ).makeError( f"Entry {index}," + "Invalid CWL, if 'entry' " "is a string, then entryName must be specified." ) expr = ( '${return {"class": "File", "basename": "' + entry.entryname + '", "contents": (function(){' + expr[2:-1] + "})() }; }" ) etool_id = "_expression_workflow_InitialWorkDirRequirement_{}".format( index ) replace_expr_with_etool( expr, etool_id, workflow, target, None, replace_etool, ) iwdr.listing[index] = ( f"$(inputs._iwdr_listing_{index}" ) generated_iwdr_reqs.append((etool_id, index)) elif entry.entryname: expression = get_expression( entry.entryname, inputs, None ) if expression: modified = True target = cwl.InputParameter( id=None, type_="string", ) etool_id = "_expression_workflow_InitialWorkDirRequirement_{}".format( index ) replace_expr_with_etool( expression, etool_id, workflow, target, None, replace_etool, ) iwdr.listing[index] = ( f"$(inputs._iwdr_listing_{index}" ) generated_iwdr_reqs.append((etool_id, index)) if generated_iwdr_reqs: prop_reqs += (cwl.InitialWorkDirRequirement,) else: iwdr = None if envVarReq and workflow.steps: for step in workflow.steps: if step.id.split("#")[-1].startswith("_expression_"): continue if step.requirements: for req in step.requirements: if isinstance(req, cwl.EnvVarRequirement): continue else: step.requirements = yaml.comments.CommentedSeq() step.requirements.append(envVarReq) for entry in generated_envVar_reqs: step.in_.append( cwl.WorkflowStepInput( id=f"_envDef{entry[1]}", source=f"{entry[0]}/result", ) ) if resourceReq and workflow.steps: for step in workflow.steps: if step.id.split("#")[-1].startswith("_expression_"): continue if step.requirements: for req in step.requirements: if isinstance(req, cwl.ResourceRequirement): continue else: step.requirements = yaml.comments.CommentedSeq() step.requirements.append(resourceReq) for entry in generated_res_reqs: step.in_.append( cwl.WorkflowStepInput( id=f"_{entry[1]}", source=f"{entry[0]}/result", ) ) if iwdr and workflow.steps: for step in workflow.steps: if step.id.split("#")[-1].startswith("_expression_"): continue if step.requirements: for req in step.requirements: if isinstance(req, cwl.InitialWorkDirRequirement): continue else: step.requirements = yaml.comments.CommentedSeq() step.requirements.append(iwdr) if generated_iwdr_reqs: for entry in generated_iwdr_reqs: step.in_.append( cwl.WorkflowStepInput( id=f"_iwdr_listing_{index}", source=f"{entry[0]}/result", ) ) else: step.in_.append( cwl.WorkflowStepInput( id="_iwdr_listing", source="_expression_workflow_InitialWorkDirRequirement/result", ) ) if workflow.requirements: workflow.requirements[:] = [ x for x in workflow.requirements if not isinstance(x, prop_reqs) ] return modified def process_level_reqs( process: cwl.CommandLineTool, step: cwl.WorkflowStep, parent: cwl.Workflow, replace_etool: bool, skip_command_line1: bool, skip_command_line2: bool, ) -> bool: """Convert expressions inside a process into new adjacent steps.""" # This is for reqs inside a Process (CommandLineTool, ExpressionTool) # differences from process_workflow_reqs_and_hints() are: # - the name of the generated ETools/CTools contains the name of the step, not "workflow" # - Generated ETools/CTools are adjacent steps # - Replace the CWL Expression inplace with a CWL parameter reference # - Don't create a new Requirement, nor delete the existing Requirement # - the Process is passed to replace_expr_with_etool for later searching for JS expressionLibs # - in addition to adding the input to the step for the ETool/CTool result, # add it to the Process.inputs as well if not process.requirements: return False modified = False target_process = step.run inputs = empty_inputs(process) generated_res_reqs: list[tuple[str, str]] = [] generated_iwdr_reqs: list[tuple[str, int | str, Any]] = [] generated_envVar_reqs: list[tuple[str, int | str]] = [] if not step.id: return False step_name = step.id.split("#", 1)[-1] for req_index, req in enumerate(process.requirements): match req: case cwl.EnvVarRequirement() if req.envDef: for env_index, envDef in enumerate(req.envDef): if envDef.envValue: expression = get_expression(envDef.envValue, inputs, None) if expression: modified = True target = cwl.InputParameter(id=None, type_="string") etool_id = "_expression_{}_EnvVarRequirement_{}".format( step_name, env_index ) replace_expr_with_etool( expression, etool_id, parent, target, None, replace_etool, process, ) target_process.requirements[req_index][ env_index ].envValue = f"$(inputs._envDef{env_index})" generated_envVar_reqs.append((etool_id, env_index)) case cwl.ResourceRequirement(): for attr in cwl.ResourceRequirement.attrs: this_attr = getattr(req, attr, None) if this_attr: expression = get_expression(this_attr, inputs, None) if expression: modified = True target = cwl.InputParameter(id=None, type_="long") etool_id = "_expression_{}_ResourceRequirement_{}".format( step_name, attr ) replace_clt_hintreq_expr_with_etool( expression, etool_id, parent, target, step, replace_etool, ) setattr( target_process.requirements[req_index], attr, f"$(inputs._{attr})", ) generated_res_reqs.append((etool_id, attr)) case cwl.InitialWorkDirRequirement() if ( not skip_command_line2 and req.listing ): if isinstance(req.listing, str): expression = get_expression(req.listing, inputs, None) if expression: modified = True target_type = cwl.InputArraySchema( ["File", "Directory"], "array", None, None ) target = cwl.InputParameter(id=None, type_=target_type) etool_id = "_expression_{}_InitialWorkDirRequirement".format( step_name ) replace_expr_with_etool( expression, etool_id, parent, target, None, replace_etool, process, ) target_process.requirements[req_index].listing = ( "$(inputs._iwdr_listing)", ) step.in_.append( cwl.WorkflowStepInput( id="_iwdr_listing", source=f"{etool_id}/result", ) ) add_input_to_process( target_process, "_iwdr_listing", target_type, process.loadingOptions, ) else: for listing_index, entry in enumerate(req.listing): expression = get_expression(entry, inputs, None) if expression: modified = True target_type = cwl.InputArraySchema( ["File", "Directory"], "array", None, None ) target = cwl.InputParameter( id=None, type_=target_type, ) etool_id = ( "_expression_{}_InitialWorkDirRequirement_{}".format( step_name, listing_index ) ) replace_expr_with_etool( expression, etool_id, parent, target, None, replace_etool, process, ) target_process.requirements[req_index].listing[ listing_index ] = f"$(inputs._iwdr_listing_{listing_index}" generated_iwdr_reqs.append( (etool_id, listing_index, target_type) ) elif isinstance(entry, cwl.Dirent): if entry.entry: expression = get_expression(entry.entry, inputs, None) if expression: modified = True if entry.entryname is not None: entryname_expr = get_expression( entry.entryname, inputs, None ) entryname = ( entry.entryname if entryname_expr else f'"{entry.entryname}"' # noqa: B907 ) new_expression = ( "${var result; var entryname = " + entryname + "; var entry = " + entry.entry[2:-1] + """; if (typeof entry === 'string' || entry instanceof String) { result = {"class": "File", "basename": entryname, "contents": entry} ; if (typeof entryname === 'string' || entryname instanceof String) { result.basename = entryname ; } } else { result = entry ; } return result; }""" ) else: new_expression = expression d_target_type = ["File", "Directory"] target = cwl.InputParameter( id=None, type_=d_target_type, ) etool_id = "_expression_{}_InitialWorkDirRequirement_{}".format( step_name, listing_index ) replace_clt_hintreq_expr_with_etool( new_expression, etool_id, parent, target, step, replace_etool, ) target_process.requirements[req_index].listing[ listing_index ].entry = "$(inputs._iwdr_listing_{})".format( listing_index ) generated_iwdr_reqs.append( (etool_id, listing_index, d_target_type) ) elif entry.entryname: expression = get_expression( entry.entryname, inputs, None ) if expression: modified = True target = cwl.InputParameter( id=None, type_="string", ) etool_id = "_expression_{}_InitialWorkDirRequirement_{}".format( step_name, listing_index ) replace_expr_with_etool( expression, etool_id, parent, target, None, replace_etool, process, ) target_process.requirements[req_index].listing[ listing_index ].entryname = "$(inputs._iwdr_listing_{})".format( listing_index ) generated_iwdr_reqs.append( (etool_id, listing_index, "string") ) for entry in generated_envVar_reqs: name = f"_envDef{entry[1]}" step.in_.append(cwl.WorkflowStepInput(id=name, source=f"{entry[0]}/result")) add_input_to_process(target_process, name, "string", process.loadingOptions) for entry in generated_res_reqs: name = f"_{entry[1]}" step.in_.append(cwl.WorkflowStepInput(id=name, source=f"{entry[0]}/result")) add_input_to_process(target_process, name, "long", process.loadingOptions) for entry in generated_iwdr_reqs: name = f"_iwdr_listing_{entry[1]}" step.in_.append(cwl.WorkflowStepInput(id=name, source=f"{entry[0]}/result")) add_input_to_process(target_process, name, entry[2], process.loadingOptions) return modified def add_input_to_process( process: cwl.Process, name: str, inptype: Any, loadingOptions: cwl.LoadingOptions ) -> None: """Add a new InputParameter to the given CommandLineTool.""" if isinstance(process, cwl.CommandLineTool): process.inputs.append( cwl.CommandInputParameter( id=name, type_=inptype, loadingOptions=loadingOptions, ) ) def traverse_CommandLineTool( clt: cwl.CommandLineTool, parent: cwl.Workflow, step: cwl.WorkflowStep, replace_etool: bool, skip_command_line1: bool, skip_command_line2: bool, ) -> bool: """Extract any CWL Expressions within the given CommandLineTool into sibling steps.""" modified = False # don't modify clt, modify step.run target_clt = step.run inputs = empty_inputs(clt) if not step.id: return False step_id = step.id.split("#")[-1] if clt.arguments and not skip_command_line1: for index, arg in enumerate(clt.arguments): if isinstance(arg, str): expression = get_expression(arg, inputs, None) if expression: modified = True inp_id = f"_arguments_{index}" etool_id = f"_expression_{step_id}{inp_id}" target_type = "Any" target = cwl.InputParameter(id=None, type_=target_type) replace_step_clt_expr_with_etool( expression, etool_id, parent, target, step, replace_etool ) target_clt.arguments[index] = cwl.CommandLineBinding( valueFrom=f"$(inputs.{inp_id})" ) target_clt.inputs.append( cwl.CommandInputParameter( id=inp_id, type_=target_type, ) ) step.in_.append( cwl.WorkflowStepInput( f"{etool_id}/result", None, inp_id, None, None ) ) remove_JSReq(target_clt, skip_command_line1) elif isinstance(arg, cwl.CommandLineBinding) and arg.valueFrom: expression = get_expression(arg.valueFrom, inputs, None) if expression: modified = True inp_id = f"_arguments_{index}" etool_id = f"_expression_{step_id}{inp_id}" target_type = "Any" target = cwl.InputParameter(id=None, type_=target_type) replace_step_clt_expr_with_etool( expression, etool_id, parent, target, step, replace_etool ) target_clt.arguments[index].valueFrom = "$(inputs.{})".format( inp_id ) target_clt.inputs.append( cwl.CommandInputParameter( id=inp_id, type_=target_type, ) ) step.in_.append( cwl.WorkflowStepInput(id=inp_id, source=f"{etool_id}/result") ) remove_JSReq(target_clt, skip_command_line1) for streamtype in "stdout", "stderr": # add 'stdin' for v1.1 version stream_value = getattr(clt, streamtype) if stream_value: expression = get_expression(stream_value, inputs, None) if expression: modified = True inp_id = f"_{streamtype}" etool_id = f"_expression_{step_id}{inp_id}" target_type = "string" target = cwl.InputParameter(id=None, type_=target_type) replace_step_clt_expr_with_etool( expression, etool_id, parent, target, step, replace_etool ) setattr(target_clt, streamtype, f"$(inputs.{inp_id})") target_clt.inputs.append( cwl.CommandInputParameter(id=inp_id, type_=target_type) ) step.in_.append( cwl.WorkflowStepInput(id=inp_id, source=f"{etool_id}/result") ) for inp in clt.inputs: if not skip_command_line1 and inp.inputBinding and inp.inputBinding.valueFrom: expression = get_expression( inp.inputBinding.valueFrom, inputs, example_input(inp.type_) ) if expression: modified = True self_id = inp.id.split("#")[-1] inp_id = f"_{self_id}_valueFrom" etool_id = f"_expression_{step_id}{inp_id}" replace_step_clt_expr_with_etool( expression, etool_id, parent, inp, step, replace_etool, self_id ) inp.inputBinding.valueFrom = f"$(inputs.{inp_id})" target_clt.inputs.append( cwl.CommandInputParameter(id=inp_id, type_=inp.type_) ) step.in_.append( cwl.WorkflowStepInput(id=inp_id, source=f"{etool_id}/result") ) for outp in clt.outputs: if outp.outputBinding: if outp.outputBinding.glob: expression = get_expression(outp.outputBinding.glob, inputs, None) if expression: modified = True inp_id = "_{}_glob".format(outp.id.split("#")[-1]) etool_id = f"_expression_{step_id}{inp_id}" glob_target_type = ["string", cwl.ArraySchema("string", "array")] target = cwl.InputParameter(id=None, type_=glob_target_type) replace_step_clt_expr_with_etool( expression, etool_id, parent, target, step, replace_etool ) outp.outputBinding.glob = f"$(inputs.{inp_id})" target_clt.inputs.append( cwl.CommandInputParameter( id=inp_id, type_=glob_target_type, ) ) step.in_.append( cwl.WorkflowStepInput(id=inp_id, source=f"{etool_id}/result") ) if outp.outputBinding.outputEval and not skip_command_line2: self: CWLOutputType = [ { "class": "File", "basename": "base.name", "nameroot": "base", "nameext": "name", "path": "/tmp/base.name", # nosec "dirname": "/tmp", # nosec } ] if outp.outputBinding.loadContents: cast(dict[Any, Any], self)[0]["contents"] = "stuff" expression = get_expression(outp.outputBinding.outputEval, inputs, self) if expression: modified = True outp_id = outp.id.split("#")[-1] inp_id = f"_{outp_id}_outputEval" etool_id = f"expression{inp_id}" sub_wf_outputs = cltool_step_outputs_to_workflow_outputs( step, etool_id, outp_id ) self_type = cwl.InputParameter( id=None, type_=cwl.InputArraySchema("File", "array", None, None), ) etool = generate_etool_from_expr( expression, outp, False, self_type, [clt, step, parent] ) if outp.outputBinding.loadContents: etool.inputs[0].type_.inputBinding = cwl.CommandLineBinding( loadContents=True ) etool.inputs.extend(cltool_inputs_to_etool_inputs(clt)) sub_wf_inputs = cltool_inputs_to_etool_inputs(clt) orig_step_inputs = copy.deepcopy(step.in_) for orig_step_input in orig_step_inputs: orig_step_input.id = orig_step_input.id.split("/")[-1] if isinstance(orig_step_input.source, MutableSequence): for index, source in enumerate(orig_step_input.source): orig_step_input.source[index] = source.split("#")[-1] else: orig_step_input.source = orig_step_input.source.split("#")[ -1 ] orig_step_inputs[:] = [ x for x in orig_step_inputs if not x.id.startswith("_") ] for inp in orig_step_inputs: inp.source = inp.id inp.linkMerge = None if replace_etool: processes = [parent] final_etool: cwl.CommandLineTool | cwl.ExpressionTool = ( etool_to_cltool(etool, find_expressionLib(processes)) ) else: final_etool = etool etool_step = cwl.WorkflowStep( id=etool_id, in_=orig_step_inputs, out=[cwl.WorkflowStepOutput("result")], run=final_etool, scatterMethod=step.scatterMethod, ) new_clt_step = copy.copy( step ) # a deepcopy would be convenient, but params2.cwl gives it problems new_clt_step.id = new_clt_step.id.split("#")[-1] new_clt_step.run = copy.copy(step.run) new_clt_step.run.id = None remove_JSReq(new_clt_step.run, skip_command_line1) for new_outp in new_clt_step.run.outputs: if new_outp.id.split("#")[-1] == outp_id: if isinstance( new_outp, ( cwl.WorkflowOutputParameter, cwl.ExpressionToolOutputParameter, ), ): new_outp.type_ = cwl.OutputArraySchema( items="File", type_="array" ) elif isinstance(new_outp, cwl.CommandOutputParameter): if new_outp.outputBinding: new_outp.outputBinding.outputEval = None new_outp.outputBinding.loadContents = None new_outp.type_ = cwl.CommandOutputArraySchema( items="File", type_="array", ) else: raise Exception( "Unimplemented OutputParameter type: %s", type(new_outp), ) new_clt_step.in_ = copy.deepcopy(step.in_) for inp in new_clt_step.in_: inp.id = inp.id.split("/")[-1] inp.source = inp.id inp.linkMerge = None for index, out in enumerate(new_clt_step.out): new_clt_step.out[index] = out.split("/")[-1] for tool_inp in new_clt_step.run.inputs: tool_inp.id = tool_inp.id.split("#")[-1] for tool_out in new_clt_step.run.outputs: tool_out.id = tool_out.id.split("#")[-1] sub_wf_steps = [new_clt_step, etool_step] sub_workflow = cwl.Workflow( inputs=sub_wf_inputs, outputs=sub_wf_outputs, steps=sub_wf_steps, cwlVersion=parent.cwlVersion, ) if step.scatter: new_clt_step.scatter = None step.run = sub_workflow rename_step_source( sub_workflow, f"{step_id}/{outp_id}", f"{etool_id}/result", ) orig_step_inputs.append( cwl.WorkflowStepInput(id="self", source=f"{step_id}/{outp_id}") ) if not parent.requirements: parent.requirements = [cwl.SubworkflowFeatureRequirement()] else: has_sub_wf_req = False for req in parent.requirements: if isinstance(req, cwl.SubworkflowFeatureRequirement): has_sub_wf_req = True if not has_sub_wf_req: parent.requirements.append( cwl.SubworkflowFeatureRequirement() ) return modified def rename_step_source(workflow: cwl.Workflow, old: str, new: str) -> None: """Update step source names to the new name.""" def simplify_wf_id(uri: str) -> str: return uri.split("#")[-1].split("/", 1)[1] def simplify_step_id(uri: str) -> str: return uri.split("#")[-1] for wf_outp in workflow.outputs: if wf_outp.outputSource and simplify_wf_id(wf_outp.outputSource) == old: wf_outp.outputSource = new for step in workflow.steps: if step.in_: for inp in step.in_: if inp.source: if isinstance(inp.source, str): source_id = ( simplify_step_id(inp.source) if "#" in inp.source else inp.source ) if source_id == old: inp.source = new else: for index, source in enumerate(inp.source): if simplify_step_id(source) == old: inp.source[index] = new def remove_JSReq( process: cwl.CommandLineTool | cwl.WorkflowStep | cwl.Workflow, skip_command_line1: bool, ) -> None: """Since the InlineJavascriptRequirement is longer needed, remove it.""" if skip_command_line1 and isinstance(process, cwl.CommandLineTool): return if process.hints: process.hints[:] = [ hint for hint in process.hints if not isinstance(hint, cwl.InlineJavascriptRequirement) ] if not process.hints: process.hints = None if process.requirements: process.requirements[:] = [ req for req in process.requirements if not isinstance(req, cwl.InlineJavascriptRequirement) ] if not process.requirements: process.requirements = None def replace_step_clt_expr_with_etool( expr: str, name: str, workflow: cwl.Workflow, target: cwl.InputParameter, step: cwl.WorkflowStep, replace_etool: bool, self_name: str | None = None, ) -> None: """Convert a step level CWL Expression to a sibling expression step.""" etool_inputs = cltool_inputs_to_etool_inputs(step.run) temp_etool = generate_etool_from_expr2( expr, target, etool_inputs, self_name, step.run, [workflow] ) if replace_etool: processes = [workflow] etool: cwl.ExpressionTool | cwl.CommandLineTool = etool_to_cltool( temp_etool, find_expressionLib(processes) ) else: etool = temp_etool wf_step_inputs = copy.deepcopy(step.in_) for wf_step_input in wf_step_inputs: wf_step_input.id = wf_step_input.id.split("/")[-1] wf_step_inputs[:] = [x for x in wf_step_inputs if not x.id.startswith("_")] workflow.steps.append( cwl.WorkflowStep( id=name, in_=wf_step_inputs, out=[cwl.WorkflowStepOutput("result")], run=etool, ) ) def replace_clt_hintreq_expr_with_etool( expr: str, name: str, workflow: cwl.Workflow, target: cwl.InputParameter, step: cwl.WorkflowStep, replace_etool: bool, self_name: str | None = None, ) -> cwl.CommandLineTool | cwl.ExpressionTool: """Factor out an expression inside a CommandLineTool req or hint into a sibling step.""" # Same as replace_step_clt_expr_with_etool or different? etool_inputs = cltool_inputs_to_etool_inputs(step.run) temp_etool = generate_etool_from_expr2( expr, target, etool_inputs, self_name, step.run, [workflow] ) if replace_etool: processes = [workflow] etool: cwl.CommandLineTool | cwl.ExpressionTool = etool_to_cltool( temp_etool, find_expressionLib(processes) ) else: etool = temp_etool wf_step_inputs = copy.deepcopy(step.in_) for wf_step_input in wf_step_inputs: wf_step_input.id = wf_step_input.id.split("/")[-1] wf_step_inputs[:] = [x for x in wf_step_inputs if not x.id.startswith("_")] workflow.steps.append( cwl.WorkflowStep( id=name, in_=wf_step_inputs, out=[cwl.WorkflowStepOutput("result")], run=etool, ) ) return etool def cltool_inputs_to_etool_inputs( tool: cwl.CommandLineTool, ) -> list[cwl.InputParameter]: """Copy CommandLineTool input objects into the equivalent ExpressionTool input objects.""" inputs = yaml.comments.CommentedSeq() if tool.inputs: for clt_inp in tool.inputs: clt_inp_id = clt_inp.id.split("#")[-1].split("/")[-1] if not clt_inp_id.startswith("_"): inputs.append( cwl.InputParameter( id=clt_inp_id, label=clt_inp.label, secondaryFiles=clt_inp.secondaryFiles, streamable=clt_inp.streamable, doc=clt_inp.doc, format=clt_inp.format, default=clt_inp.default, type_=clt_inp.type_, extension_fields=clt_inp.extension_fields, loadingOptions=clt_inp.loadingOptions, ) ) return inputs def cltool_step_outputs_to_workflow_outputs( cltool_step: cwl.WorkflowStep, etool_step_id: str, etool_out_id: str ) -> list[cwl.OutputParameter]: """ Copy CommandLineTool outputs into the equivalent Workflow output parameters. Connects the outputSources for each of the new output parameters to the step they came from. """ outputs = yaml.comments.CommentedSeq() if not cltool_step.id: raise WorkflowException(f"Missing step id from {cltool_step}.") default_step_id = cltool_step.id.split("#")[-1] if cltool_step.run.outputs: for clt_out in cltool_step.run.outputs: clt_out_id = clt_out.id.split("#")[-1].split("/")[-1] if clt_out_id == etool_out_id: outputSource = f"{etool_step_id}/result" else: outputSource = f"{default_step_id}/{clt_out_id}" if not clt_out_id.startswith("_"): outputs.append( cwl.WorkflowOutputParameter( id=clt_out_id, label=clt_out.label, secondaryFiles=clt_out.secondaryFiles, streamable=clt_out.streamable, doc=clt_out.doc, format=clt_out.format, outputSource=outputSource, type_=clt_out.type_, extension_fields=clt_out.extension_fields, loadingOptions=clt_out.loadingOptions, ) ) return outputs def generate_etool_from_expr2( expr: str, target: cwl.InputParameter, inputs: Sequence[ cwl.InputParameter | cwl.CommandInputParameter | cwl.CommandOutputParameter ], self_name: str | None = None, process: cwl.CommandLineTool | cwl.ExpressionTool | None = None, extra_processes: None | ( Sequence[cwl.Workflow | cwl.WorkflowStep | cwl.CommandLineTool] ) = None, ) -> cwl.ExpressionTool: """Generate an ExpressionTool to achieve the same result as the given expression.""" outputs = yaml.comments.CommentedSeq() outputs.append( cwl.ExpressionToolOutputParameter( id="result", label=target.label, secondaryFiles=target.secondaryFiles, streamable=target.streamable, doc=target.doc, format=target.format, type_=target.type_, ) ) expression = "${" if self_name: expression += f"\n var self=inputs.{self_name};" expression += ( """ return {"result": function(){""" + expr[2:-2] + """}()}; }""" ) hints = None procs: list[ cwl.CommandLineTool | cwl.ExpressionTool | cwl.Workflow | cwl.WorkflowStep ] = [] if process: procs.append(process) if extra_processes: procs.extend(extra_processes) inlineJSReq = cwl.InlineJavascriptRequirement(find_expressionLib(procs)) reqs = [inlineJSReq] if process: if process.hints: hints = copy.deepcopy(process.hints) hints[:] = [ x for x in hints if not isinstance(x, cwl.InitialWorkDirRequirement) ] if process.requirements: reqs.extend(copy.deepcopy(process.requirements)) reqs[:] = [ x for x in reqs if not isinstance(x, cwl.InitialWorkDirRequirement) ] return cwl.ExpressionTool( id="_:" + str(uuid.uuid4()), inputs=inputs, outputs=outputs, expression=expression, requirements=reqs, cwlVersion="v1.0", ) def traverse_step( step: cwl.WorkflowStep, parent: cwl.Workflow, replace_etool: bool, skip_command_line1: bool, skip_command_line2: bool, ) -> bool: """Process the given WorkflowStep.""" modified = False inputs = empty_inputs(step, parent) if not step.id: return False step_id = step.id.split("#")[-1] original_process = copy.deepcopy(step.run) original_step_ins = copy.deepcopy(step.in_) for inp in step.in_: if inp.valueFrom: if not inp.source: self = None else: if isinstance(inp.source, MutableSequence): self = [] for source in inp.source: if not step.scatter: self.append( example_input( utils.type_for_source(parent, source.split("#")[-1]) ) ) else: scattered_source_type = utils.type_for_source( parent, source ) if isinstance(scattered_source_type, list): for stype in scattered_source_type: self.append(example_input(stype.type_)) else: self.append(example_input(scattered_source_type.type_)) else: if not step.scatter: self = example_input( utils.type_for_source(parent, inp.source.split("#")[-1]) ) else: scattered_source_type2 = utils.type_for_source( parent, inp.source ) if isinstance(scattered_source_type2, list): self = example_input(scattered_source_type2[0].type_) else: self = example_input(scattered_source_type2.type_) expression = get_expression(inp.valueFrom, inputs, self) if expression: modified = True etool_id = "_expression_{}_{}".format(step_id, inp.id.split("/")[-1]) target = get_input_for_id(inp.id, original_process) if not target: raise WorkflowException("target not found") input_source_id = None source_type: ( None | MutableSequence[cwl.InputParameter | cwl.CommandOutputParameter] | cwl.InputParameter | cwl.CommandOutputParameter ) = None if inp.source: if isinstance(inp.source, MutableSequence): input_source_id = [] source_types: list[cwl.InputParameter] = [] for source in inp.source: source_id = source.split("#")[-1] input_source_id.append(source_id) temp_type = utils.type_for_source( step.run, source_id, parent ) if isinstance(temp_type, list): for ttype in temp_type: if ttype not in source_types: source_types.append(ttype) else: if temp_type not in source_types: source_types.append(temp_type) source_type = cwl.InputParameter( id=None, type_=cwl.ArraySchema(source_types, "array"), ) else: input_source_id = inp.source.split("#")[-1] source_type = utils.param_for_source_id( step.run, input_source_id, parent ) # target.id = target.id.split('#')[-1] if isinstance(original_process, cwl.ExpressionTool): found_JSReq = False reqs: list[cwl.ProcessRequirement] = [] if original_process.hints: reqs.extend(original_process.hints) if original_process.requirements: reqs.extend(original_process.requirements) for req in reqs: if isinstance(req, cwl.InlineJavascriptRequirement): found_JSReq = True if not found_JSReq: if not step.run.requirements: step.run.requirements = [] expr_lib = find_expressionLib([parent]) step.run.requirements.append( cwl.InlineJavascriptRequirement(expr_lib) ) replace_step_valueFrom_expr_with_etool( expression, etool_id, parent, target, step, inp, original_process, original_step_ins, input_source_id, replace_etool, source_type, ) inp.valueFrom = None inp.source = f"{etool_id}/result" # TODO: skip or special process for sub workflows? process_modified = process_level_reqs( original_process, step, parent, replace_etool, skip_command_line1, skip_command_line2, ) if process_modified: modified = True if isinstance(original_process, cwl.CommandLineTool): clt_modified = traverse_CommandLineTool( original_process, parent, step, replace_etool, skip_command_line1, skip_command_line2, ) if clt_modified: modified = True return modified def workflow_step_to_InputParameters( step_ins: list[cwl.WorkflowStepInput], parent: cwl.Workflow, except_in_id: str ) -> list[cwl.InputParameter | cwl.CommandOutputParameter]: """Create InputParameters to match the given WorkflowStep inputs.""" params = [] for inp in step_ins: if not inp.id: continue inp_id = inp.id.split("#")[-1].split("/")[-1] if inp.source and inp_id != except_in_id: param = copy.deepcopy( utils.param_for_source_id(parent, sourcenames=inp.source) ) if isinstance(param, MutableSequence): for p in param: if not p.type_: raise WorkflowException( f"Don't know how to get type id for {p!r}." ) p.id = inp_id p.type_ = clean_type_ids(p.type_) params.append(p) else: if not param.type_: raise WorkflowException( f"Don't know how to get type id for {param!r}." ) param.id = inp_id param.type_ = clean_type_ids(param.type_) params.append(param) return params def replace_step_valueFrom_expr_with_etool( expr: str, name: str, workflow: cwl.Workflow, target: cwl.CommandInputParameter | cwl.InputParameter, step: cwl.WorkflowStep, step_inp: cwl.WorkflowStepInput, original_process: cwl.CommandLineTool | cwl.ExpressionTool, original_step_ins: list[cwl.WorkflowStepInput], source: str | list[str] | None, replace_etool: bool, source_type: ( cwl.InputParameter | cwl.CommandOutputParameter | MutableSequence[cwl.InputParameter | cwl.CommandOutputParameter] | None ) = None, ) -> None: """Replace a WorkflowStep level 'valueFrom' expression with a sibling ExpressionTool step.""" if not step_inp.id: raise WorkflowException(f"Missing id in {step_inp}.") step_inp_id = step_inp.id.split("/")[-1] etool_inputs = workflow_step_to_InputParameters( original_step_ins, workflow, step_inp_id ) if source: source_param = cwl.InputParameter(id="self", type_="Any") # TODO: would be nicer to derive a proper type; but in the face of linkMerge, this is easier for now etool_inputs.append(source_param) temp_etool = generate_etool_from_expr2( expr, target, etool_inputs, "self" if source else None, original_process, [workflow, step], ) if replace_etool: processes: list[ (cwl.Workflow | cwl.CommandLineTool | cwl.ExpressionTool | cwl.WorkflowStep) ] = [ workflow, step, ] cltool = etool_to_cltool(temp_etool, find_expressionLib(processes)) etool: cwl.ExpressionTool | cwl.CommandLineTool = cltool else: etool = temp_etool wf_step_inputs = copy.deepcopy(original_step_ins) if source: wf_step_inputs.append(cwl.WorkflowStepInput(id="self", source=step_inp.source)) for wf_step_input in wf_step_inputs: wf_step_input.id = wf_step_input.id.split("/")[-1] if wf_step_input.valueFrom: wf_step_input.valueFrom = None if wf_step_input.source: if isinstance(wf_step_input.source, MutableSequence): for index, inp_source in enumerate(wf_step_input.source): wf_step_input.source[index] = inp_source.split("#")[-1] else: wf_step_input.source = wf_step_input.source.split("#")[-1] wf_step_inputs[:] = [ x for x in wf_step_inputs if x.id and not (x.id.startswith("_") or x.id.endswith(step_inp_id)) ] scatter = copy.deepcopy(step.scatter) if isinstance(scatter, str): scatter = [scatter] if isinstance(scatter, MutableSequence): for index, entry in enumerate(scatter): scatter[index] = entry.split("/")[-1] if scatter and step_inp_id in scatter: scatter = ["self"] # do we still need to scatter? else: scatter = None workflow.steps.append( cwl.WorkflowStep( id=name, in_=wf_step_inputs, out=[cwl.WorkflowStepOutput("result")], run=etool, scatter=scatter, scatterMethod=step.scatterMethod, ) ) def traverse_workflow( workflow: cwl.Workflow, replace_etool: bool, skip_command_line1: bool, skip_command_line2: bool, ) -> tuple[cwl.Workflow, bool]: """Traverse a workflow, processing each step.""" modified = False for index, step in enumerate(workflow.steps): if isinstance(step.run, cwl.ExpressionTool) and replace_etool: workflow.steps[index].run = etool_to_cltool(step.run) modified = True else: step_modified = load_step( step, replace_etool, skip_command_line1, skip_command_line2 ) if step_modified: modified = True for step in workflow.steps: if not step.id.startswith("_expression"): step_modified = traverse_step( step, workflow, replace_etool, skip_command_line1, skip_command_line2 ) if step_modified: modified = True if process_workflow_inputs_and_outputs(workflow, replace_etool): modified = True if process_workflow_reqs_and_hints(workflow, replace_etool): modified = True if workflow.requirements: workflow.requirements[:] = [ x for x in workflow.requirements if not isinstance( x, (cwl.InlineJavascriptRequirement, cwl.StepInputExpressionRequirement) ) ] else: workflow.requirements = None return workflow, modified cwl_utils-0.41/cwl_utils/cwl_v1_1_expression_refactor.py0000755000000000000000000025362113615410400020535 0ustar00#!/usr/bin/env python3 # SPDX-License-Identifier: Apache-2.0 # Copyright 2018-2021 Michael R. Crusoe """CWL Expression refactoring tool for CWL v1.1 .""" import copy import hashlib import uuid from collections.abc import MutableSequence, Sequence from contextlib import suppress from typing import Any, cast from ruamel import yaml from schema_salad.sourceline import SourceLine from schema_salad.utils import json_dumps import cwl_utils.parser.cwl_v1_1 as cwl import cwl_utils.parser.cwl_v1_1_utils as utils from cwl_utils.errors import JavascriptException, WorkflowException from cwl_utils.expression import do_eval, interpolate from cwl_utils.types import ( CWLDirectoryType, CWLFileType, CWLObjectType, CWLOutputType, CWLParameterContext, CWLRuntimeParameterContext, is_file_or_directory, ) def expand_stream_shortcuts(process: cwl.CommandLineTool) -> cwl.CommandLineTool: """Rewrite the "type: stdout" shortcut to use an explicit random filename.""" if not process.outputs: return process result = None for index, output in enumerate(process.outputs): if output.type_ == "stdout": # TODO: add 'stdin' for CWL v1.1 if not result: result = copy.deepcopy(process) stdout_path = process.stdout if not stdout_path: stdout_path = hashlib.sha1( # nosec json_dumps(cwl.save(process)).encode("utf-8") ).hexdigest() result.stdout = stdout_path result.outputs[index].type_ = "File" output.outputBinding = cwl.CommandOutputBinding(stdout_path, None, None) if result: return result return process def escape_expression_field(contents: str) -> str: """Escape sequences similar to CWL expressions or param references.""" return contents.replace("${", "$/{").replace("$(", "$/(") def clean_type_ids( cwltype: cwl.ArraySchema | cwl.InputRecordSchema, ) -> cwl.ArraySchema | cwl.InputRecordSchema: """Simplify type identifiers.""" result = copy.deepcopy(cwltype) if isinstance(result, cwl.ArraySchema): if isinstance(result.items, MutableSequence): for item in result.items: if hasattr(item, "id"): item.id = item.id.split("#")[-1] elif isinstance(result.items, cwl.InputRecordSchema): if result.items.name: result.items.name = result.items.name.split("/")[-1] if result.items.fields: for field in result.items.fields: field.name = field.name.split("/")[-1] elif isinstance(result, cwl.InputRecordSchema): if result.name: result.name = result.name.split("/")[-1] if result.fields: for field in result.fields: field.name = field.name.split("/")[-1] return result def get_expression( string: str, inputs: CWLObjectType, self: CWLOutputType | None ) -> str | None: """ Find and return a normalized CWL expression, if any. CWL expressions in the $() form are converted to the ${} form. """ if not isinstance(string, str): return None if string.strip().startswith("${"): return string if "$(" in string: runtime = CWLRuntimeParameterContext( cores=0, ram=0, outdir="/root", tmpdir="/tmp", # nosec outdirSize=0, tmpdirSize=0, ) try: do_eval( string, inputs, context=self, requirements=[], outdir="", tmpdir="", resources={}, ) except (WorkflowException, JavascriptException): if ( string[0:2] != "$(" or not string.endswith(")") or len(string.split("$(")) > 2 ): # then it is a string interpolation return cast( str, interpolate( scan=string, rootvars=CWLParameterContext( inputs=inputs, self=self, runtime=runtime ), fullJS=True, escaping_behavior=2, convert_to_expression=True, ), ) else: # it is a CWL Expression in $() with no string interpolation return "${return " + string.strip()[2:-1] + ";}" return None def etool_to_cltool( etool: cwl.ExpressionTool, expressionLib: list[str] | None = None ) -> cwl.CommandLineTool: """Convert a ExpressionTool to a CommandLineTool.""" inputs = yaml.comments.CommentedSeq() # preserve the order for inp in etool.inputs: inputs.append( cwl.CommandInputParameter( id=inp.id, label=inp.label, secondaryFiles=inp.secondaryFiles, streamable=inp.streamable, doc=inp.doc, format=inp.format, default=inp.default, type_=inp.type_, extension_fields=inp.extension_fields, loadingOptions=inp.loadingOptions, ) ) outputs = yaml.comments.CommentedSeq() for outp in etool.outputs: outputs.append( cwl.CommandOutputParameter( id=outp.id, label=outp.label, secondaryFiles=outp.secondaryFiles, streamable=outp.streamable, doc=outp.doc, format=outp.format, type_=outp.type_, extension_fields=outp.extension_fields, loadingOptions=outp.loadingOptions, ) ) contents = """"use strict"; var inputs=$(inputs); var runtime=$(runtime);""" if expressionLib: contents += "\n" + "\n".join(expressionLib) contents += ( """ var ret = function(){""" + escape_expression_field(etool.expression.strip()[2:-1]) + """}(); process.stdout.write(JSON.stringify(ret));""" ) listing = [cwl.Dirent(entryname="expression.js", entry=contents, writable=None)] iwdr = cwl.InitialWorkDirRequirement(listing) containerReq = cwl.DockerRequirement(dockerPull="node:alpine") softwareHint = cwl.SoftwareRequirement( packages=[cwl.SoftwarePackage(package="nodejs")] ) return cwl.CommandLineTool( inputs=inputs, outputs=outputs, id=etool.id, requirements=[iwdr], hints=[containerReq, softwareHint], label=etool.label, doc=etool.doc, cwlVersion=etool.cwlVersion, baseCommand=["nodejs", "expression.js"], stdout="cwl.output.json", extension_fields=etool.extension_fields, loadingOptions=etool.loadingOptions, ) def traverse( process: cwl.CommandLineTool | cwl.ExpressionTool | cwl.Workflow, replace_etool: bool, inside: bool, skip_command_line1: bool, skip_command_line2: bool, ) -> tuple[cwl.CommandLineTool | cwl.ExpressionTool | cwl.Workflow, bool]: """Convert the given process and any subprocesses.""" match process: case cwl.CommandLineTool() if not inside: process = expand_stream_shortcuts(process) wf_inputs = [] wf_outputs = [] step_inputs = [] step_outputs = [] if process.inputs: for inp in process.inputs: inp_id = inp.id.split("#")[-1] step_inputs.append( cwl.WorkflowStepInput( id=inp_id, source=inp_id, extension_fields=inp.extension_fields, loadingOptions=inp.loadingOptions, ) ) wf_inputs.append( cwl.WorkflowInputParameter( id=inp_id, label=inp.label, secondaryFiles=inp.secondaryFiles, streamable=inp.streamable, doc=inp.doc, format=inp.format, default=inp.default, type_=inp.type_, extension_fields=inp.extension_fields, loadingOptions=inp.loadingOptions, ) ) if process.outputs: for outp in process.outputs: outp_id = outp.id.split("#")[-1] step_outputs.append(outp_id) wf_outputs.append( cwl.WorkflowOutputParameter( id=outp_id, label=outp.label, secondaryFiles=outp.secondaryFiles, streamable=outp.streamable, doc=outp.doc, format=outp.format, outputSource=f"main/{outp_id}", type_=outp.type_, extension_fields=outp.extension_fields, loadingOptions=outp.loadingOptions, ) ) step = cwl.WorkflowStep( id="#main", in_=step_inputs, out=step_outputs, run=copy.deepcopy(process), ) workflow = cwl.Workflow( inputs=wf_inputs, outputs=wf_outputs, steps=[step], cwlVersion=process.cwlVersion, ) result, modified = traverse_workflow( workflow, replace_etool, skip_command_line1, skip_command_line2 ) if modified: return result, True else: return process, False case cwl.ExpressionTool() if replace_etool: expression = get_expression(process.expression, empty_inputs(process), None) # Why call get_expression on an ExpressionTool? # It normalizes the form of $() CWL expressions into the ${} style if expression: process2 = copy.deepcopy(process) process2.expression = expression else: process2 = process return etool_to_cltool(process2), True case cwl.Workflow(): return traverse_workflow( process, replace_etool, skip_command_line1, skip_command_line2 ) case _: return process, False def load_step( step: cwl.WorkflowStep, replace_etool: bool, skip_command_line1: bool, skip_command_line2: bool, ) -> bool: """If the step's Process is not inline, load and process it.""" modified = False if isinstance(step.run, str): step.run, modified = traverse( cwl.load_document(step.run, baseuri=step.loadingOptions.fileuri), replace_etool, True, skip_command_line1, skip_command_line2, ) return modified def generate_etool_from_expr( expr: str, target: cwl.CommandInputParameter | cwl.WorkflowInputParameter, no_inputs: bool = False, self_type: None | ( cwl.WorkflowInputParameter | cwl.CommandInputParameter | list[cwl.WorkflowInputParameter | cwl.CommandInputParameter] ) = None, # if the "self" input should be a different type than the "result" output extra_processes: None | ( Sequence[cwl.Workflow | cwl.WorkflowStep | cwl.CommandLineTool] ) = None, ) -> cwl.ExpressionTool: """Convert a CWL Expression into an ExpressionTool.""" inputs = yaml.comments.CommentedSeq() if not no_inputs: if not self_type: self_type = target if isinstance(self_type, list): new_type: ( list[cwl.ArraySchema | cwl.InputRecordSchema] | cwl.ArraySchema | cwl.InputRecordSchema ) = [clean_type_ids(t.type_) for t in self_type] else: new_type = clean_type_ids(self_type.type_) inputs.append( cwl.WorkflowInputParameter( id="self", label=self_type.label if not isinstance(self_type, list) else None, secondaryFiles=( self_type.secondaryFiles if not isinstance(self_type, list) else None ), streamable=( self_type.streamable if not isinstance(self_type, list) else None ), doc=self_type.doc if not isinstance(self_type, list) else None, format=self_type.format if not isinstance(self_type, list) else None, type_=new_type, extension_fields=( self_type.extension_fields if not isinstance(self_type, list) else None ), loadingOptions=( self_type.loadingOptions if not isinstance(self_type, list) else None ), ) ) outputs = yaml.comments.CommentedSeq() outputs.append( cwl.ExpressionToolOutputParameter( id="result", label=target.label, secondaryFiles=target.secondaryFiles, streamable=target.streamable, doc=target.doc, format=target.format, type_=target.type_, extension_fields=target.extension_fields, loadingOptions=target.loadingOptions, ) ) expression = "${" if not no_inputs: expression += "\n var self=inputs.self;" expression += ( """ return {"result": function(){""" + expr[2:-2] + """}()}; }""" ) inlineJSReq = cwl.InlineJavascriptRequirement( find_expressionLib(extra_processes) if extra_processes else None ) return cwl.ExpressionTool( id="_:" + str(uuid.uuid4()), inputs=inputs, outputs=outputs, expression=expression, requirements=[inlineJSReq], cwlVersion="v1.0", ) def get_input_for_id( name: str, tool: cwl.CommandLineTool | cwl.Workflow ) -> cwl.CommandInputParameter | None: """Determine the CommandInputParameter for the given input name.""" name = name.split("/")[-1] for inp in cast(list[cwl.CommandInputParameter], tool.inputs): if inp.id and inp.id.split("#")[-1].split("/")[-1] == name: return inp if isinstance(tool, cwl.Workflow) and "/" in name: stepname, stem = name.split("/", 1) for step in tool.steps: if step.id == stepname: result = get_input_for_id(stem, step.run) if result: return result return None def find_expressionLib( processes: Sequence[ cwl.CommandLineTool | cwl.Workflow | cwl.ExpressionTool | cwl.WorkflowStep ], ) -> list[str] | None: """ Return the expressionLib from the highest priority InlineJavascriptRequirement. processes: should be in order of least important to most important (Workflow, WorkflowStep, ... CommandLineTool/ExpressionTool) """ for process in reversed(copy.copy(processes)): if process.requirements: for req in process.requirements: if isinstance(req, cwl.InlineJavascriptRequirement): return cast(list[str] | None, copy.deepcopy(req.expressionLib)) return None def replace_expr_with_etool( expr: str, name: str, workflow: cwl.Workflow, target: cwl.CommandInputParameter | cwl.WorkflowInputParameter, source: str | list[Any] | None, replace_etool: bool = False, extra_process: None | ( cwl.Workflow | cwl.WorkflowStep | cwl.CommandLineTool ) = None, source_type: cwl.CommandInputParameter | None = None, ) -> None: """Modify the given workflow, replacing the expr with an standalone ExpressionTool.""" extra_processes: list[cwl.Workflow | cwl.WorkflowStep | cwl.CommandLineTool] = [ workflow ] if extra_process: extra_processes.append(extra_process) etool: cwl.ExpressionTool = generate_etool_from_expr( expr, target, source is None, source_type, extra_processes ) if replace_etool: processes: list[cwl.WorkflowStep | cwl.Workflow | cwl.CommandLineTool] = [ workflow ] if extra_process: processes.append(extra_process) final_tool: cwl.ExpressionTool | cwl.CommandLineTool = etool_to_cltool( etool, find_expressionLib(processes) ) else: final_tool = etool inps = [] if source: inps.append(cwl.WorkflowStepInput(id="self", source=source)) workflow.steps.append( cwl.WorkflowStep( id=name, in_=inps, out=[cwl.WorkflowStepOutput("result")], run=final_tool, ) ) def replace_wf_input_ref_with_step_output( workflow: cwl.Workflow, name: str, target: str ) -> None: """Refactor all reference to a workflow input to the specified step output.""" if workflow.steps: for step in workflow.steps: if step.in_: for inp in step.in_: if inp.source: if inp.source == name: inp.source = target if isinstance(inp.source, MutableSequence): for index, source in enumerate(inp.source): if source == name: inp.source[index] = target if workflow.outputs: for outp in workflow.outputs: if outp.outputSource: if outp.outputSource == name: outp.outputSource = target if isinstance(outp.outputSource, MutableSequence): for index, outputSource in enumerate(outp.outputSource): if outputSource == name: outp.outputSource[index] = target def empty_inputs( process_or_step: ( cwl.CommandLineTool | cwl.WorkflowStep | cwl.ExpressionTool | cwl.Workflow ), parent: cwl.Workflow | None = None, ) -> dict[str, Any]: """Produce a mock input object for the given inputs.""" result = {} if isinstance(process_or_step, cwl.Process): for param in process_or_step.inputs: result[param.id.split("#")[-1]] = example_input(param.type_) else: for param in process_or_step.in_: param_id = param.id.split("/")[-1] if param.source is None and param.valueFrom: result[param_id] = example_input("string") elif param.source is None and param.default: result[param_id] = param.default else: with suppress(WorkflowException): result[param_id] = example_input( utils.type_for_source(process_or_step.run, param.source, parent) ) return result def example_input(some_type: Any) -> Any: """Produce a fake input for the given type.""" # TODO: accept some sort of context object with local custom type definitions if some_type == "Directory": return CWLDirectoryType( **{ "class": "Directory", "location": "https://www.example.com/example", "basename": "example", "listing": [ CWLFileType( **{ "class": "File", "basename": "example.txt", "size": 23, "contents": "hoopla", "nameroot": "example", "nameext": "txt", } ) ], } ) if some_type == "File": return CWLFileType( **{ "class": "File", "location": "https://www.example.com/example.txt", "basename": "example.txt", "size": 23, "contents": "hoopla", "nameroot": "example", "nameext": "txt", } ) if some_type == "int": return 23 if some_type == "string": return "hoopla!" if some_type == "boolean": return True return None EMPTY_FILE = CWLFileType( **{ "class": "File", "basename": "em.pty", "nameroot": "em", "nameext": "pty", } ) TOPLEVEL_SF_EXPR_ERROR = ( "Input '{}'. Sorry, CWL Expressions as part of a secondaryFiles " "specification in a Workflow level input or standalone CommandLine Tool " "are not able to be refactored into separate ExpressionTool or " "CommandLineTool steps." ) TOPLEVEL_FORMAT_EXPR_ERROR = ( "Input '{}'. Sorry, CWL Expressions as part of a format " "specification in a Workflow level input are not able to be refactored " "into separate ExpressionTool/CommandLineTool steps." ) def process_workflow_inputs_and_outputs( workflow: cwl.Workflow, replace_etool: bool ) -> bool: """Do any needed conversions on the given Workflow's inputs and outputs.""" modified = False inputs = empty_inputs(workflow) for index, param in enumerate(workflow.inputs): with SourceLine(workflow.inputs, index, WorkflowException): if param.format and get_expression(param.format, inputs, None): raise SourceLine( param.loadingOptions.original_doc, "format", raise_type=WorkflowException, ).makeError(TOPLEVEL_FORMAT_EXPR_ERROR.format(param.id.split("#")[-1])) if param.secondaryFiles: if hasattr(param.secondaryFiles, "pattern") and get_expression( param.secondaryFiles.pattern, inputs, EMPTY_FILE ): raise SourceLine( param.loadingOptions.original_doc, "secondaryFiles", raise_type=WorkflowException, ).makeError(TOPLEVEL_SF_EXPR_ERROR.format(param.id.split("#")[-1])) elif isinstance(param.secondaryFiles, MutableSequence): for index2, entry in enumerate(param.secondaryFiles): if get_expression(entry.pattern, inputs, EMPTY_FILE): raise SourceLine( param.loadingOptions.original_doc, index2, raise_type=WorkflowException, ).makeError( f"Entry {index}," + TOPLEVEL_SF_EXPR_ERROR.format(param.id.split("#")[-1]) ) return modified def process_workflow_reqs_and_hints( workflow: cwl.Workflow, replace_etool: bool ) -> bool: """ Convert any expressions in a workflow's reqs and hints. Each expression will be converted to an additional step. The converted requirement will be copied to all workflow steps that don't have that requirement type. Those affected steps will gain an additional input from the relevant synthesized expression step. """ # TODO: consolidate the generated etools/cltools into a single "_expression_workflow_reqs" step # TODO: support resourceReq.* references to Workflow.inputs? # ^ By refactoring replace_expr_etool to allow multiple inputs, # and connecting all workflow inputs to the generated step modified = False inputs = empty_inputs(workflow) generated_res_reqs: list[tuple[str, int | str]] = [] generated_iwdr_reqs: list[tuple[str, int | str]] = [] generated_envVar_reqs: list[tuple[str, int | str]] = [] prop_reqs: tuple[ ( type[cwl.EnvVarRequirement] | type[cwl.ResourceRequirement] | type[cwl.InitialWorkDirRequirement] ), ..., ] = () resourceReq: cwl.ResourceRequirement | None = None envVarReq: cwl.EnvVarRequirement | None = None iwdr: cwl.InitialWorkDirRequirement | None = None if workflow.requirements is not None: for req in cast(list[cwl.ProcessRequirement], workflow.requirements): match req: case cwl.EnvVarRequirement() if req.envDef: for index, envDef in enumerate(req.envDef): if envDef.envValue: expression = get_expression(envDef.envValue, inputs, None) if expression: modified = True target = cwl.WorkflowInputParameter( id=None, type_="string", ) etool_id = ( "_expression_workflow_EnvVarRequirement_{}".format( index ) ) replace_expr_with_etool( expression, etool_id, workflow, target, None, replace_etool, ) if envVarReq is None: envVarReq = copy.deepcopy(req) prop_reqs += (cwl.EnvVarRequirement,) newEnvDef = copy.deepcopy(envDef) newEnvDef.envValue = f"$(inputs._envDef{index})" envVarReq.envDef[index] = newEnvDef generated_envVar_reqs.append((etool_id, index)) case cwl.ResourceRequirement(): for attr in cwl.ResourceRequirement.attrs: this_attr = getattr(req, attr, None) if this_attr: expression = get_expression(this_attr, inputs, None) if expression: modified = True target = cwl.WorkflowInputParameter( id=None, type_="long" ) etool_id = "_expression_workflow_ResourceRequirement_{}".format( attr ) replace_expr_with_etool( expression, etool_id, workflow, target, None, replace_etool, ) if not resourceReq: resourceReq = cwl.ResourceRequirement( loadingOptions=workflow.loadingOptions, ) prop_reqs += (cwl.ResourceRequirement,) setattr(resourceReq, attr, f"$(inputs._{attr})") generated_res_reqs.append((etool_id, attr)) case cwl.InitialWorkDirRequirement() if req.listing: if isinstance(req.listing, str): expression = get_expression(req.listing, inputs, None) if expression: modified = True target = cwl.WorkflowInputParameter( id=None, type_=cwl.InputArraySchema( ["File", "Directory"], "array", None, None ), ) etool_id = "_expression_workflow_InitialWorkDirRequirement" replace_expr_with_etool( expression, etool_id, workflow, target, None, replace_etool, ) iwdr = cwl.InitialWorkDirRequirement( listing="$(inputs._iwdr_listing)", loadingOptions=workflow.loadingOptions, ) prop_reqs += (cwl.InitialWorkDirRequirement,) else: iwdr = copy.deepcopy(req) for index, entry in enumerate(req.listing): expression = get_expression(entry, inputs, None) if expression: modified = True target = cwl.WorkflowInputParameter( id=None, type_=cwl.InputArraySchema( ["File", "Directory"], "array", None, None ), ) etool_id = "_expression_workflow_InitialWorkDirRequirement_{}".format( index ) replace_expr_with_etool( expression, etool_id, workflow, target, None, replace_etool, ) iwdr.listing[index] = f"$(inputs._iwdr_listing_{index}" generated_iwdr_reqs.append((etool_id, index)) elif isinstance(entry, cwl.Dirent): if entry.entry: expression = get_expression( entry.entry, inputs, None ) if expression: expr: str = expression expr_result = do_eval( ex=entry.entry, jobinput=inputs, requirements=[], outdir="", tmpdir="", resources={}, ) modified = True if is_file_or_directory(expr_result): target = cwl.WorkflowInputParameter( id=None, type_=expr_result["class"], ) replace_expr_with_etool( expr, etool_id, workflow, target, None, replace_etool, ) iwdr.listing[index] = ( "$(inputs._iwdr_listing_{}".format( index ) ) generated_iwdr_reqs.append( (etool_id, index) ) elif isinstance(expr_result, str): target = cwl.WorkflowInputParameter( id=None, type_=["File"], ) if entry.entryname is None: raise SourceLine( entry.loadingOptions.original_doc, index, raise_type=WorkflowException, ).makeError( f"Entry {index}," + "Invalid CWL, if 'entry' " "is a string, then entryName must be specified." ) expr = ( '${return {"class": "File", "basename": "' + entry.entryname + '", "contents": (function(){' + expr[2:-1] + "})() }; }" ) etool_id = "_expression_workflow_InitialWorkDirRequirement_{}".format( index ) replace_expr_with_etool( expr, etool_id, workflow, target, None, replace_etool, ) iwdr.listing[index] = ( f"$(inputs._iwdr_listing_{index}" ) generated_iwdr_reqs.append((etool_id, index)) elif entry.entryname: expression = get_expression( entry.entryname, inputs, None ) if expression: modified = True target = cwl.WorkflowInputParameter( id=None, type_="string", ) etool_id = "_expression_workflow_InitialWorkDirRequirement_{}".format( index ) replace_expr_with_etool( expression, etool_id, workflow, target, None, replace_etool, ) iwdr.listing[index] = ( f"$(inputs._iwdr_listing_{index}" ) generated_iwdr_reqs.append((etool_id, index)) if generated_iwdr_reqs: prop_reqs += (cwl.InitialWorkDirRequirement,) else: iwdr = None if envVarReq and workflow.steps: for step in workflow.steps: if step.id.split("#")[-1].startswith("_expression_"): continue if step.requirements: for req in step.requirements: if isinstance(req, cwl.EnvVarRequirement): continue else: step.requirements = yaml.comments.CommentedSeq() step.requirements.append(envVarReq) for entry in generated_envVar_reqs: step.in_.append( cwl.WorkflowStepInput( id=f"_envDef{entry[1]}", source=f"{entry[0]}/result", ) ) if resourceReq and workflow.steps: for step in workflow.steps: if step.id.split("#")[-1].startswith("_expression_"): continue if step.requirements: for req in step.requirements: if isinstance(req, cwl.ResourceRequirement): continue else: step.requirements = yaml.comments.CommentedSeq() step.requirements.append(resourceReq) for entry in generated_res_reqs: step.in_.append( cwl.WorkflowStepInput( id=f"_{entry[1]}", source=f"{entry[0]}/result", ) ) if iwdr and workflow.steps: for step in workflow.steps: if step.id.split("#")[-1].startswith("_expression_"): continue if step.requirements: for req in step.requirements: if isinstance(req, cwl.InitialWorkDirRequirement): continue else: step.requirements = yaml.comments.CommentedSeq() step.requirements.append(iwdr) if generated_iwdr_reqs: for entry in generated_iwdr_reqs: step.in_.append( cwl.WorkflowStepInput( id=f"_iwdr_listing_{index}", source=f"{entry[0]}/result", ) ) else: step.in_.append( cwl.WorkflowStepInput( id="_iwdr_listing", source="_expression_workflow_InitialWorkDirRequirement/result", ) ) if workflow.requirements: workflow.requirements[:] = [ x for x in workflow.requirements if not isinstance(x, prop_reqs) ] return modified def process_level_reqs( process: cwl.CommandLineTool, step: cwl.WorkflowStep, parent: cwl.Workflow, replace_etool: bool, skip_command_line1: bool, skip_command_line2: bool, ) -> bool: """Convert expressions inside a process into new adjacent steps.""" # This is for reqs inside a Process (CommandLineTool, ExpressionTool) # differences from process_workflow_reqs_and_hints() are: # - the name of the generated ETools/CTools contains the name of the step, not "workflow" # - Generated ETools/CTools are adjacent steps # - Replace the CWL Expression inplace with a CWL parameter reference # - Don't create a new Requirement, nor delete the existing Requirement # - the Process is passed to replace_expr_with_etool for later searching for JS expressionLibs # - in addition to adding the input to the step for the ETool/CTool result, # add it to the Process.inputs as well if not process.requirements: return False modified = False target_process = step.run inputs = empty_inputs(process) generated_res_reqs: list[tuple[str, str]] = [] generated_iwdr_reqs: list[tuple[str, int | str, Any]] = [] generated_envVar_reqs: list[tuple[str, int | str]] = [] if not step.id: return False step_name = step.id.split("#", 1)[-1] for req_index, req in enumerate(process.requirements): match req: case cwl.EnvVarRequirement() if req.envDef: for env_index, envDef in enumerate(req.envDef): if envDef.envValue: expression = get_expression(envDef.envValue, inputs, None) if expression: modified = True target = cwl.WorkflowInputParameter(id=None, type_="string") etool_id = "_expression_{}_EnvVarRequirement_{}".format( step_name, env_index ) replace_expr_with_etool( expression, etool_id, parent, target, None, replace_etool, process, ) target_process.requirements[req_index][ env_index ].envValue = f"$(inputs._envDef{env_index})" generated_envVar_reqs.append((etool_id, env_index)) case cwl.ResourceRequirement(): for attr in cwl.ResourceRequirement.attrs: this_attr = getattr(req, attr, None) if this_attr: expression = get_expression(this_attr, inputs, None) if expression: modified = True target = cwl.WorkflowInputParameter(id=None, type_="long") etool_id = "_expression_{}_ResourceRequirement_{}".format( step_name, attr ) replace_clt_hintreq_expr_with_etool( expression, etool_id, parent, target, step, replace_etool, ) setattr( target_process.requirements[req_index], attr, f"$(inputs._{attr})", ) generated_res_reqs.append((etool_id, attr)) case cwl.InitialWorkDirRequirement() if ( not skip_command_line2 and req.listing ): if isinstance(req.listing, str): expression = get_expression(req.listing, inputs, None) if expression: modified = True target_type = cwl.InputArraySchema( ["File", "Directory"], "array", None, None ) target = cwl.WorkflowInputParameter(id=None, type_=target_type) etool_id = "_expression_{}_InitialWorkDirRequirement".format( step_name ) replace_expr_with_etool( expression, etool_id, parent, target, None, replace_etool, process, ) target_process.requirements[req_index].listing = ( "$(inputs._iwdr_listing)", ) step.in_.append( cwl.WorkflowStepInput( id="_iwdr_listing", source=f"{etool_id}/result", ) ) add_input_to_process( target_process, "_iwdr_listing", target_type, process.loadingOptions, ) else: for listing_index, entry in enumerate(req.listing): expression = get_expression(entry, inputs, None) if expression: modified = True target_type = cwl.InputArraySchema( ["File", "Directory"], "array", None, None ) target = cwl.WorkflowInputParameter( id=None, type_=target_type, ) etool_id = ( "_expression_{}_InitialWorkDirRequirement_{}".format( step_name, listing_index ) ) replace_expr_with_etool( expression, etool_id, parent, target, None, replace_etool, process, ) target_process.requirements[req_index].listing[ listing_index ] = f"$(inputs._iwdr_listing_{listing_index}" generated_iwdr_reqs.append( (etool_id, listing_index, target_type) ) elif isinstance(entry, cwl.Dirent): if entry.entry: expression = get_expression(entry.entry, inputs, None) if expression: modified = True if entry.entryname is not None: entryname_expr = get_expression( entry.entryname, inputs, None ) entryname = ( entry.entryname if entryname_expr else f'"{entry.entryname}"' # noqa: B907 ) new_expression = ( "${var result; var entryname = " + entryname + "; var entry = " + entry.entry[2:-1] + """; if (typeof entry === 'string' || entry instanceof String) { result = {"class": "File", "basename": entryname, "contents": entry} ; if (typeof entryname === 'string' || entryname instanceof String) { result.basename = entryname ; } } else { result = entry ; } return result; }""" ) else: new_expression = expression d_target_type = ["File", "Directory"] target = cwl.WorkflowInputParameter( id=None, type_=d_target_type, ) etool_id = "_expression_{}_InitialWorkDirRequirement_{}".format( step_name, listing_index ) replace_clt_hintreq_expr_with_etool( new_expression, etool_id, parent, target, step, replace_etool, ) target_process.requirements[req_index].listing[ listing_index ].entry = "$(inputs._iwdr_listing_{})".format( listing_index ) generated_iwdr_reqs.append( (etool_id, listing_index, d_target_type) ) elif entry.entryname: expression = get_expression( entry.entryname, inputs, None ) if expression: modified = True target = cwl.WorkflowInputParameter( id=None, type_="string", ) etool_id = "_expression_{}_InitialWorkDirRequirement_{}".format( step_name, listing_index ) replace_expr_with_etool( expression, etool_id, parent, target, None, replace_etool, process, ) target_process.requirements[req_index].listing[ listing_index ].entryname = "$(inputs._iwdr_listing_{})".format( listing_index ) generated_iwdr_reqs.append( (etool_id, listing_index, "string") ) for entry in generated_envVar_reqs: name = f"_envDef{entry[1]}" step.in_.append(cwl.WorkflowStepInput(id=name, source=f"{entry[0]}/result")) add_input_to_process(target_process, name, "string", process.loadingOptions) for entry in generated_res_reqs: name = f"_{entry[1]}" step.in_.append(cwl.WorkflowStepInput(id=name, source=f"{entry[0]}/result")) add_input_to_process(target_process, name, "long", process.loadingOptions) for entry in generated_iwdr_reqs: name = f"_iwdr_listing_{entry[1]}" step.in_.append(cwl.WorkflowStepInput(id=name, source=f"{entry[0]}/result")) add_input_to_process(target_process, name, entry[2], process.loadingOptions) return modified def add_input_to_process( process: cwl.Process, name: str, inptype: Any, loadingOptions: cwl.LoadingOptions ) -> None: """Add a new InputParameter to the given CommandLineTool.""" if isinstance(process, cwl.CommandLineTool): process.inputs.append( cwl.CommandInputParameter( id=name, type_=inptype, loadingOptions=loadingOptions, ) ) def traverse_CommandLineTool( clt: cwl.CommandLineTool, parent: cwl.Workflow, step: cwl.WorkflowStep, replace_etool: bool, skip_command_line1: bool, skip_command_line2: bool, ) -> bool: """Extract any CWL Expressions within the given CommandLineTool into sibling steps.""" modified = False # don't modify clt, modify step.run target_clt = step.run inputs = empty_inputs(clt) if not step.id: return False step_id = step.id.split("#")[-1] if clt.arguments and not skip_command_line1: for index, arg in enumerate(clt.arguments): if isinstance(arg, str): expression = get_expression(arg, inputs, None) if expression: modified = True inp_id = f"_arguments_{index}" etool_id = f"_expression_{step_id}{inp_id}" target_type = "Any" target = cwl.WorkflowInputParameter(id=None, type_=target_type) replace_step_clt_expr_with_etool( expression, etool_id, parent, target, step, replace_etool ) target_clt.arguments[index] = cwl.CommandLineBinding( valueFrom=f"$(inputs.{inp_id})" ) target_clt.inputs.append( cwl.CommandInputParameter( id=inp_id, type_=target_type, ) ) step.in_.append( cwl.WorkflowStepInput( f"{etool_id}/result", None, inp_id, None, None ) ) remove_JSReq(target_clt, skip_command_line1) elif isinstance(arg, cwl.CommandLineBinding) and arg.valueFrom: expression = get_expression(arg.valueFrom, inputs, None) if expression: modified = True inp_id = f"_arguments_{index}" etool_id = f"_expression_{step_id}{inp_id}" target_type = "Any" target = cwl.WorkflowInputParameter(id=None, type_=target_type) replace_step_clt_expr_with_etool( expression, etool_id, parent, target, step, replace_etool ) target_clt.arguments[index].valueFrom = "$(inputs.{})".format( inp_id ) target_clt.inputs.append( cwl.CommandInputParameter( id=inp_id, type_=target_type, ) ) step.in_.append( cwl.WorkflowStepInput(id=inp_id, source=f"{etool_id}/result") ) remove_JSReq(target_clt, skip_command_line1) for streamtype in "stdout", "stderr": # add 'stdin' for v1.1 version stream_value = getattr(clt, streamtype) if stream_value: expression = get_expression(stream_value, inputs, None) if expression: modified = True inp_id = f"_{streamtype}" etool_id = f"_expression_{step_id}{inp_id}" target_type = "string" target = cwl.WorkflowInputParameter(id=None, type_=target_type) replace_step_clt_expr_with_etool( expression, etool_id, parent, target, step, replace_etool ) setattr(target_clt, streamtype, f"$(inputs.{inp_id})") target_clt.inputs.append( cwl.CommandInputParameter(id=inp_id, type_=target_type) ) step.in_.append( cwl.WorkflowStepInput(id=inp_id, source=f"{etool_id}/result") ) for inp in clt.inputs: if not skip_command_line1 and inp.inputBinding and inp.inputBinding.valueFrom: expression = get_expression( inp.inputBinding.valueFrom, inputs, example_input(inp.type_) ) if expression: modified = True self_id = inp.id.split("#")[-1] inp_id = f"_{self_id}_valueFrom" etool_id = f"_expression_{step_id}{inp_id}" replace_step_clt_expr_with_etool( expression, etool_id, parent, inp, step, replace_etool, self_id ) inp.inputBinding.valueFrom = f"$(inputs.{inp_id})" target_clt.inputs.append( cwl.CommandInputParameter(id=inp_id, type_=inp.type_) ) step.in_.append( cwl.WorkflowStepInput(id=inp_id, source=f"{etool_id}/result") ) for outp in clt.outputs: if outp.outputBinding: if outp.outputBinding.glob: expression = get_expression(outp.outputBinding.glob, inputs, None) if expression: modified = True inp_id = "_{}_glob".format(outp.id.split("#")[-1]) etool_id = f"_expression_{step_id}{inp_id}" glob_target_type = ["string", cwl.ArraySchema("string", "array")] target = cwl.WorkflowInputParameter(id=None, type_=glob_target_type) replace_step_clt_expr_with_etool( expression, etool_id, parent, target, step, replace_etool ) outp.outputBinding.glob = f"$(inputs.{inp_id})" target_clt.inputs.append( cwl.CommandInputParameter( id=inp_id, type_=glob_target_type, ) ) step.in_.append( cwl.WorkflowStepInput(id=inp_id, source=f"{etool_id}/result") ) if outp.outputBinding.outputEval and not skip_command_line2: self: CWLOutputType = [ { "class": "File", "basename": "base.name", "nameroot": "base", "nameext": "name", "path": "/tmp/base.name", # nosec "dirname": "/tmp", # nosec } ] if outp.outputBinding.loadContents: cast(dict[Any, Any], self)[0]["contents"] = "stuff" expression = get_expression(outp.outputBinding.outputEval, inputs, self) if expression: modified = True outp_id = outp.id.split("#")[-1] inp_id = f"_{outp_id}_outputEval" etool_id = f"expression{inp_id}" sub_wf_outputs = cltool_step_outputs_to_workflow_outputs( step, etool_id, outp_id ) self_type = cwl.WorkflowInputParameter( id=None, type_=cwl.InputArraySchema("File", "array", None, None), ) etool = generate_etool_from_expr( expression, outp, False, self_type, [clt, step, parent] ) if outp.outputBinding.loadContents: etool.inputs[0].type_.inputBinding = cwl.CommandLineBinding( loadContents=True ) etool.inputs.extend(cltool_inputs_to_etool_inputs(clt)) sub_wf_inputs = cltool_inputs_to_etool_inputs(clt) orig_step_inputs = copy.deepcopy(step.in_) for orig_step_input in orig_step_inputs: orig_step_input.id = orig_step_input.id.split("/")[-1] if isinstance(orig_step_input.source, MutableSequence): for index, source in enumerate(orig_step_input.source): orig_step_input.source[index] = source.split("#")[-1] else: orig_step_input.source = orig_step_input.source.split("#")[ -1 ] orig_step_inputs[:] = [ x for x in orig_step_inputs if not x.id.startswith("_") ] for inp in orig_step_inputs: inp.source = inp.id inp.linkMerge = None if replace_etool: processes = [parent] final_etool: cwl.CommandLineTool | cwl.ExpressionTool = ( etool_to_cltool(etool, find_expressionLib(processes)) ) else: final_etool = etool etool_step = cwl.WorkflowStep( id=etool_id, in_=orig_step_inputs, out=[cwl.WorkflowStepOutput("result")], run=final_etool, scatterMethod=step.scatterMethod, ) new_clt_step = copy.copy( step ) # a deepcopy would be convenient, but params2.cwl gives it problems new_clt_step.id = new_clt_step.id.split("#")[-1] new_clt_step.run = copy.copy(step.run) new_clt_step.run.id = None remove_JSReq(new_clt_step.run, skip_command_line1) for new_outp in new_clt_step.run.outputs: if new_outp.id.split("#")[-1] == outp_id: if isinstance( new_outp, ( cwl.WorkflowOutputParameter, cwl.ExpressionToolOutputParameter, ), ): new_outp.type_ = cwl.OutputArraySchema( items="File", type_="array" ) elif isinstance(new_outp, cwl.CommandOutputParameter): if new_outp.outputBinding: new_outp.outputBinding.outputEval = None new_outp.outputBinding.loadContents = None new_outp.type_ = cwl.CommandOutputArraySchema( items="File", type_="array", ) else: raise Exception( "Unimplemented OutputParameter type: %s", type(new_outp), ) new_clt_step.in_ = copy.deepcopy(step.in_) for inp in new_clt_step.in_: inp.id = inp.id.split("/")[-1] inp.source = inp.id inp.linkMerge = None for index, out in enumerate(new_clt_step.out): new_clt_step.out[index] = out.split("/")[-1] for tool_inp in new_clt_step.run.inputs: tool_inp.id = tool_inp.id.split("#")[-1] for tool_out in new_clt_step.run.outputs: tool_out.id = tool_out.id.split("#")[-1] sub_wf_steps = [new_clt_step, etool_step] sub_workflow = cwl.Workflow( inputs=sub_wf_inputs, outputs=sub_wf_outputs, steps=sub_wf_steps, cwlVersion=parent.cwlVersion, ) if step.scatter: new_clt_step.scatter = None step.run = sub_workflow rename_step_source( sub_workflow, f"{step_id}/{outp_id}", f"{etool_id}/result", ) orig_step_inputs.append( cwl.WorkflowStepInput(id="self", source=f"{step_id}/{outp_id}") ) if not parent.requirements: parent.requirements = [cwl.SubworkflowFeatureRequirement()] else: has_sub_wf_req = False for req in parent.requirements: if isinstance(req, cwl.SubworkflowFeatureRequirement): has_sub_wf_req = True if not has_sub_wf_req: parent.requirements.append( cwl.SubworkflowFeatureRequirement() ) return modified def rename_step_source(workflow: cwl.Workflow, old: str, new: str) -> None: """Update step source names to the new name.""" def simplify_wf_id(uri: str) -> str: return uri.split("#")[-1].split("/", 1)[1] def simplify_step_id(uri: str) -> str: return uri.split("#")[-1] for wf_outp in workflow.outputs: if wf_outp.outputSource and simplify_wf_id(wf_outp.outputSource) == old: wf_outp.outputSource = new for step in workflow.steps: if step.in_: for inp in step.in_: if inp.source: if isinstance(inp.source, str): source_id = ( simplify_step_id(inp.source) if "#" in inp.source else inp.source ) if source_id == old: inp.source = new else: for index, source in enumerate(inp.source): if simplify_step_id(source) == old: inp.source[index] = new def remove_JSReq( process: cwl.CommandLineTool | cwl.WorkflowStep | cwl.Workflow, skip_command_line1: bool, ) -> None: """Since the InlineJavascriptRequirement is longer needed, remove it.""" if skip_command_line1 and isinstance(process, cwl.CommandLineTool): return if process.hints: process.hints[:] = [ hint for hint in process.hints if not isinstance(hint, cwl.InlineJavascriptRequirement) ] if not process.hints: process.hints = None if process.requirements: process.requirements[:] = [ req for req in process.requirements if not isinstance(req, cwl.InlineJavascriptRequirement) ] if not process.requirements: process.requirements = None def replace_step_clt_expr_with_etool( expr: str, name: str, workflow: cwl.Workflow, target: cwl.WorkflowInputParameter, step: cwl.WorkflowStep, replace_etool: bool, self_name: str | None = None, ) -> None: """Convert a step level CWL Expression to a sibling expression step.""" etool_inputs = cltool_inputs_to_etool_inputs(step.run) temp_etool = generate_etool_from_expr2( expr, target, etool_inputs, self_name, step.run, [workflow] ) if replace_etool: processes = [workflow] etool: cwl.ExpressionTool | cwl.CommandLineTool = etool_to_cltool( temp_etool, find_expressionLib(processes) ) else: etool = temp_etool wf_step_inputs = copy.deepcopy(step.in_) for wf_step_input in wf_step_inputs: wf_step_input.id = wf_step_input.id.split("/")[-1] wf_step_inputs[:] = [x for x in wf_step_inputs if not x.id.startswith("_")] workflow.steps.append( cwl.WorkflowStep( id=name, in_=wf_step_inputs, out=[cwl.WorkflowStepOutput("result")], run=etool, ) ) def replace_clt_hintreq_expr_with_etool( expr: str, name: str, workflow: cwl.Workflow, target: cwl.WorkflowInputParameter, step: cwl.WorkflowStep, replace_etool: bool, self_name: str | None = None, ) -> cwl.CommandLineTool | cwl.ExpressionTool: """Factor out an expression inside a CommandLineTool req or hint into a sibling step.""" # Same as replace_step_clt_expr_with_etool or different? etool_inputs = cltool_inputs_to_etool_inputs(step.run) temp_etool = generate_etool_from_expr2( expr, target, etool_inputs, self_name, step.run, [workflow] ) if replace_etool: processes = [workflow] etool: cwl.CommandLineTool | cwl.ExpressionTool = etool_to_cltool( temp_etool, find_expressionLib(processes) ) else: etool = temp_etool wf_step_inputs = copy.deepcopy(step.in_) for wf_step_input in wf_step_inputs: wf_step_input.id = wf_step_input.id.split("/")[-1] wf_step_inputs[:] = [x for x in wf_step_inputs if not x.id.startswith("_")] workflow.steps.append( cwl.WorkflowStep( id=name, in_=wf_step_inputs, out=[cwl.WorkflowStepOutput("result")], run=etool, ) ) return etool def cltool_inputs_to_etool_inputs( tool: cwl.CommandLineTool, ) -> list[cwl.WorkflowInputParameter]: """Copy CommandLineTool input objects into the equivalent ExpressionTool input objects.""" inputs = yaml.comments.CommentedSeq() if tool.inputs: for clt_inp in tool.inputs: clt_inp_id = clt_inp.id.split("#")[-1].split("/")[-1] if not clt_inp_id.startswith("_"): inputs.append( cwl.WorkflowInputParameter( id=clt_inp_id, label=clt_inp.label, secondaryFiles=clt_inp.secondaryFiles, streamable=clt_inp.streamable, doc=clt_inp.doc, format=clt_inp.format, default=clt_inp.default, type_=clt_inp.type_, extension_fields=clt_inp.extension_fields, loadingOptions=clt_inp.loadingOptions, ) ) return inputs def cltool_step_outputs_to_workflow_outputs( cltool_step: cwl.WorkflowStep, etool_step_id: str, etool_out_id: str ) -> list[cwl.OutputParameter]: """ Copy CommandLineTool outputs into the equivalent Workflow output parameters. Connects the outputSources for each of the new output parameters to the step they came from. """ outputs = yaml.comments.CommentedSeq() if not cltool_step.id: raise WorkflowException(f"Missing step id from {cltool_step}.") default_step_id = cltool_step.id.split("#")[-1] if cltool_step.run.outputs: for clt_out in cltool_step.run.outputs: clt_out_id = clt_out.id.split("#")[-1].split("/")[-1] if clt_out_id == etool_out_id: outputSource = f"{etool_step_id}/result" else: outputSource = f"{default_step_id}/{clt_out_id}" if not clt_out_id.startswith("_"): outputs.append( cwl.WorkflowOutputParameter( id=clt_out_id, label=clt_out.label, secondaryFiles=clt_out.secondaryFiles, streamable=clt_out.streamable, doc=clt_out.doc, format=clt_out.format, outputSource=outputSource, type_=clt_out.type_, extension_fields=clt_out.extension_fields, loadingOptions=clt_out.loadingOptions, ) ) return outputs def generate_etool_from_expr2( expr: str, target: cwl.CommandInputParameter | cwl.WorkflowInputParameter, inputs: Sequence[ cwl.WorkflowInputParameter | cwl.CommandInputParameter | cwl.CommandOutputParameter ], self_name: str | None = None, process: cwl.CommandLineTool | cwl.ExpressionTool | None = None, extra_processes: None | ( Sequence[cwl.Workflow | cwl.WorkflowStep | cwl.CommandLineTool] ) = None, ) -> cwl.ExpressionTool: """Generate an ExpressionTool to achieve the same result as the given expression.""" outputs = yaml.comments.CommentedSeq() outputs.append( cwl.ExpressionToolOutputParameter( id="result", label=target.label, secondaryFiles=target.secondaryFiles, streamable=target.streamable, doc=target.doc, format=target.format, type_=target.type_, ) ) expression = "${" if self_name: expression += f"\n var self=inputs.{self_name};" expression += ( """ return {"result": function(){""" + expr[2:-2] + """}()}; }""" ) hints = None procs: list[ cwl.CommandLineTool | cwl.ExpressionTool | cwl.Workflow | cwl.WorkflowStep ] = [] if process: procs.append(process) if extra_processes: procs.extend(extra_processes) inlineJSReq = cwl.InlineJavascriptRequirement(find_expressionLib(procs)) reqs = [inlineJSReq] if process: if process.hints: hints = copy.deepcopy(process.hints) hints[:] = [ x for x in hints if not isinstance(x, cwl.InitialWorkDirRequirement) ] if process.requirements: reqs.extend(copy.deepcopy(process.requirements)) reqs[:] = [ x for x in reqs if not isinstance(x, cwl.InitialWorkDirRequirement) ] return cwl.ExpressionTool( id="_:" + str(uuid.uuid4()), inputs=inputs, outputs=outputs, expression=expression, requirements=reqs, cwlVersion="v1.0", ) def traverse_step( step: cwl.WorkflowStep, parent: cwl.Workflow, replace_etool: bool, skip_command_line1: bool, skip_command_line2: bool, ) -> bool: """Process the given WorkflowStep.""" modified = False inputs = empty_inputs(step, parent) if not step.id: return False step_id = step.id.split("#")[-1] original_process = copy.deepcopy(step.run) original_step_ins = copy.deepcopy(step.in_) for inp in step.in_: if inp.valueFrom: if not inp.source: self = None else: if isinstance(inp.source, MutableSequence): self = [] for source in inp.source: if not step.scatter: self.append( example_input( utils.type_for_source(parent, source.split("#")[-1]) ) ) else: scattered_source_type = utils.type_for_source( parent, source ) if isinstance(scattered_source_type, list): for stype in scattered_source_type: self.append(example_input(stype.type_)) else: self.append(example_input(scattered_source_type.type_)) else: if not step.scatter: self = example_input( utils.type_for_source(parent, inp.source.split("#")[-1]) ) else: scattered_source_type2 = utils.type_for_source( parent, inp.source ) if isinstance(scattered_source_type2, list): self = example_input(scattered_source_type2[0].type_) else: self = example_input(scattered_source_type2.type_) expression = get_expression(inp.valueFrom, inputs, self) if expression: modified = True etool_id = "_expression_{}_{}".format(step_id, inp.id.split("/")[-1]) target = get_input_for_id(inp.id, original_process) if not target: raise WorkflowException("target not found") input_source_id = None source_type: None | ( MutableSequence[ cwl.CommandInputParameter | cwl.CommandOutputParameter | cwl.WorkflowInputParameter ] | cwl.CommandInputParameter | cwl.CommandOutputParameter | cwl.WorkflowInputParameter ) = None if inp.source: if isinstance(inp.source, MutableSequence): input_source_id = [] source_types: list[cwl.WorkflowInputParameter] = [] for source in inp.source: source_id = source.split("#")[-1] input_source_id.append(source_id) temp_type = utils.type_for_source( step.run, source_id, parent ) if isinstance(temp_type, list): for ttype in temp_type: if ttype not in source_types: source_types.append(ttype) else: if temp_type not in source_types: source_types.append(temp_type) source_type = cwl.WorkflowInputParameter( id=None, type_=cwl.ArraySchema(source_types, "array"), ) else: input_source_id = inp.source.split("#")[-1] source_type = utils.param_for_source_id( step.run, input_source_id, parent ) # target.id = target.id.split('#')[-1] if isinstance(original_process, cwl.ExpressionTool): found_JSReq = False reqs: list[cwl.ProcessRequirement] = [] if original_process.hints: reqs.extend(original_process.hints) if original_process.requirements: reqs.extend(original_process.requirements) for req in reqs: if isinstance(req, cwl.InlineJavascriptRequirement): found_JSReq = True if not found_JSReq: if not step.run.requirements: step.run.requirements = [] expr_lib = find_expressionLib([parent]) step.run.requirements.append( cwl.InlineJavascriptRequirement(expr_lib) ) replace_step_valueFrom_expr_with_etool( expression, etool_id, parent, target, step, inp, original_process, original_step_ins, input_source_id, replace_etool, source_type, ) inp.valueFrom = None inp.source = f"{etool_id}/result" # TODO: skip or special process for sub workflows? process_modified = process_level_reqs( original_process, step, parent, replace_etool, skip_command_line1, skip_command_line2, ) if process_modified: modified = True if isinstance(original_process, cwl.CommandLineTool): clt_modified = traverse_CommandLineTool( original_process, parent, step, replace_etool, skip_command_line1, skip_command_line2, ) if clt_modified: modified = True return modified def workflow_step_to_WorkflowInputParameters( step_ins: list[cwl.WorkflowStepInput], parent: cwl.Workflow, except_in_id: str ) -> MutableSequence[ cwl.CommandInputParameter | cwl.CommandOutputParameter | cwl.WorkflowInputParameter ]: """Create WorkflowInputParameters to match the given WorkflowStep inputs.""" params = [] for inp in step_ins: if not inp.id: continue inp_id = inp.id.split("#")[-1].split("/")[-1] if inp.source and inp_id != except_in_id: param = copy.deepcopy( utils.param_for_source_id(parent, sourcenames=inp.source) ) if isinstance(param, MutableSequence): for p in param: p.id = inp_id p.type_ = clean_type_ids(p.type_) params.append(p) else: param.id = inp_id param.type_ = clean_type_ids(param.type_) params.append(param) return params def replace_step_valueFrom_expr_with_etool( expr: str, name: str, workflow: cwl.Workflow, target: cwl.CommandInputParameter | cwl.WorkflowInputParameter, step: cwl.WorkflowStep, step_inp: cwl.WorkflowStepInput, original_process: cwl.CommandLineTool | cwl.ExpressionTool, original_step_ins: list[cwl.WorkflowStepInput], source: str | list[str] | None, replace_etool: bool, source_type: None | ( cwl.CommandInputParameter | cwl.CommandOutputParameter | cwl.WorkflowInputParameter | MutableSequence[ cwl.CommandInputParameter | cwl.CommandOutputParameter | cwl.WorkflowInputParameter ] ) = None, ) -> None: """Replace a WorkflowStep level 'valueFrom' expression with a sibling ExpressionTool step.""" if not step_inp.id: raise WorkflowException(f"Missing id in {step_inp}.") step_inp_id = step_inp.id.split("/")[-1] etool_inputs = workflow_step_to_WorkflowInputParameters( original_step_ins, workflow, step_inp_id ) if source: source_param = cwl.WorkflowInputParameter(id="self", type_="Any") # TODO: would be nicer to derive a proper type; but in the face of linkMerge, this is easier for now etool_inputs.append(source_param) temp_etool = generate_etool_from_expr2( expr, target, etool_inputs, "self" if source else None, original_process, [workflow, step], ) if replace_etool: processes: list[ (cwl.Workflow | cwl.CommandLineTool | cwl.ExpressionTool | cwl.WorkflowStep) ] = [ workflow, step, ] cltool = etool_to_cltool(temp_etool, find_expressionLib(processes)) etool: cwl.ExpressionTool | cwl.CommandLineTool = cltool else: etool = temp_etool wf_step_inputs = copy.deepcopy(original_step_ins) if source: wf_step_inputs.append(cwl.WorkflowStepInput(id="self", source=step_inp.source)) for wf_step_input in wf_step_inputs: if not wf_step_input.id: continue wf_step_input.id = wf_step_input.id.split("/")[-1] if wf_step_input.valueFrom: wf_step_input.valueFrom = None if wf_step_input.source: if isinstance(wf_step_input.source, MutableSequence): for index, inp_source in enumerate(wf_step_input.source): wf_step_input.source[index] = inp_source.split("#")[-1] else: wf_step_input.source = wf_step_input.source.split("#")[-1] wf_step_inputs[:] = [ x for x in wf_step_inputs if x.id and not (x.id.startswith("_") or x.id.endswith(step_inp_id)) ] scatter = copy.deepcopy(step.scatter) if isinstance(scatter, str): scatter = [scatter] if isinstance(scatter, MutableSequence): for index, entry in enumerate(scatter): scatter[index] = entry.split("/")[-1] if scatter and step_inp_id in scatter: scatter = ["self"] # do we still need to scatter? else: scatter = None workflow.steps.append( cwl.WorkflowStep( id=name, in_=wf_step_inputs, out=[cwl.WorkflowStepOutput("result")], run=etool, scatter=scatter, scatterMethod=step.scatterMethod, ) ) def traverse_workflow( workflow: cwl.Workflow, replace_etool: bool, skip_command_line1: bool, skip_command_line2: bool, ) -> tuple[cwl.Workflow, bool]: """Traverse a workflow, processing each step.""" modified = False for index, step in enumerate(workflow.steps): if isinstance(step.run, cwl.ExpressionTool) and replace_etool: workflow.steps[index].run = etool_to_cltool(step.run) modified = True else: step_modified = load_step( step, replace_etool, skip_command_line1, skip_command_line2 ) if step_modified: modified = True for step in workflow.steps: if not step.id.startswith("_expression"): step_modified = traverse_step( step, workflow, replace_etool, skip_command_line1, skip_command_line2 ) if step_modified: modified = True if process_workflow_inputs_and_outputs(workflow, replace_etool): modified = True if process_workflow_reqs_and_hints(workflow, replace_etool): modified = True if workflow.requirements: workflow.requirements[:] = [ x for x in workflow.requirements if not isinstance( x, (cwl.InlineJavascriptRequirement, cwl.StepInputExpressionRequirement) ) ] else: workflow.requirements = None return workflow, modified cwl_utils-0.41/cwl_utils/cwl_v1_2_expression_refactor.py0000755000000000000000000027062613615410400020542 0ustar00#!/usr/bin/env python3 # SPDX-License-Identifier: Apache-2.0 # Copyright 2018-2021 Michael R. Crusoe """CWL Expression refactoring tool for CWL v1.2 .""" import copy import hashlib import uuid from collections.abc import Mapping, MutableSequence, Sequence from contextlib import suppress from typing import Any, cast from ruamel import yaml from schema_salad.sourceline import SourceLine from schema_salad.utils import json_dumps import cwl_utils.parser.cwl_v1_2 as cwl import cwl_utils.parser.cwl_v1_2_utils as utils from cwl_utils.errors import JavascriptException, WorkflowException from cwl_utils.expression import do_eval, interpolate from cwl_utils.types import ( CWLDirectoryType, CWLFileType, CWLObjectType, CWLOutputType, CWLParameterContext, CWLRuntimeParameterContext, ) def expand_stream_shortcuts(process: cwl.CommandLineTool) -> cwl.CommandLineTool: """Rewrite the "type: stdout" shortcut to use an explicit random filename.""" if not process.outputs: return process result = None for index, output in enumerate(process.outputs): if output.type_ == "stdout": # TODO: add 'stdin' for CWL v1.1 if not result: result = copy.deepcopy(process) stdout_path = process.stdout if not stdout_path: stdout_path = hashlib.sha1( # nosec json_dumps(cwl.save(process)).encode("utf-8") ).hexdigest() result.stdout = stdout_path result.outputs[index].type_ = "File" output.outputBinding = cwl.CommandOutputBinding(stdout_path, None, None) if result: return result return process def escape_expression_field(contents: str) -> str: """Escape sequences similar to CWL expressions or param references.""" return contents.replace("${", "$/{").replace("$(", "$/(") def clean_type_ids( cwltype: cwl.ArraySchema | cwl.InputRecordSchema, ) -> cwl.ArraySchema | cwl.InputRecordSchema: """Simplify type identifiers.""" result = copy.deepcopy(cwltype) if isinstance(result, cwl.ArraySchema): if isinstance(result.items, MutableSequence): for item in result.items: if hasattr(item, "id"): item.id = item.id.split("#")[-1] elif isinstance(result.items, cwl.InputRecordSchema): if result.items.name: result.items.name = result.items.name.split("/")[-1] if result.items.fields: for field in result.items.fields: field.name = field.name.split("/")[-1] elif isinstance(result, cwl.InputRecordSchema): if result.name: result.name = result.name.split("/")[-1] if result.fields: for field in result.fields: field.name = field.name.split("/")[-1] return result def get_expression( string: str, inputs: CWLObjectType, self: CWLOutputType | None ) -> str | None: """ Find and return a normalized CWL expression, if any. CWL expressions in the $() form are converted to the ${} form. """ if not isinstance(string, str): return None if string.strip().startswith("${"): return string if "$(" in string: runtime = CWLRuntimeParameterContext( cores=0, ram=0, outdir="/root", tmpdir="/tmp", # nosec outdirSize=0, tmpdirSize=0, ) try: do_eval( string, inputs, context=self, requirements=[], outdir="", tmpdir="", resources={}, ) except (WorkflowException, JavascriptException): if ( string[0:2] != "$(" or not string.endswith(")") or len(string.split("$(")) > 2 ): # then it is a string interpolation return cast( str, interpolate( scan=string, rootvars=CWLParameterContext( inputs=inputs, self=self, runtime=runtime ), fullJS=True, escaping_behavior=2, convert_to_expression=True, ), ) else: # it is a CWL Expression in $() with no string interpolation return "${return " + string.strip()[2:-1] + ";}" return None def etool_to_cltool( etool: cwl.ExpressionTool, expressionLib: list[str] | None = None ) -> cwl.CommandLineTool: """Convert a ExpressionTool to a CommandLineTool.""" inputs = yaml.comments.CommentedSeq() # preserve the order for inp in etool.inputs: inputs.append( cwl.CommandInputParameter( id=inp.id, label=inp.label, secondaryFiles=inp.secondaryFiles, streamable=inp.streamable, doc=inp.doc, format=inp.format, default=inp.default, type_=inp.type_, extension_fields=inp.extension_fields, loadingOptions=inp.loadingOptions, ) ) outputs = yaml.comments.CommentedSeq() for outp in etool.outputs: outputs.append( cwl.CommandOutputParameter( id=outp.id, label=outp.label, secondaryFiles=outp.secondaryFiles, streamable=outp.streamable, doc=outp.doc, format=outp.format, type_=outp.type_, extension_fields=outp.extension_fields, loadingOptions=outp.loadingOptions, ) ) contents = """"use strict"; var inputs=$(inputs); var runtime=$(runtime);""" if expressionLib: contents += "\n" + "\n".join(expressionLib) contents += ( """ var ret = function(){""" + escape_expression_field(etool.expression.strip()[2:-1]) + """}(); process.stdout.write(JSON.stringify(ret));""" ) listing = [cwl.Dirent(entryname="expression.js", entry=contents, writable=None)] iwdr = cwl.InitialWorkDirRequirement(listing) containerReq = cwl.DockerRequirement(dockerPull="node:alpine") softwareHint = cwl.SoftwareRequirement( packages=[cwl.SoftwarePackage(package="nodejs")] ) return cwl.CommandLineTool( inputs=inputs, outputs=outputs, id=etool.id, requirements=[iwdr], hints=[containerReq, softwareHint], label=etool.label, doc=etool.doc, cwlVersion=etool.cwlVersion, baseCommand=["nodejs", "expression.js"], stdout="cwl.output.json", extension_fields=etool.extension_fields, loadingOptions=etool.loadingOptions, ) def traverse( process: cwl.CommandLineTool | cwl.ExpressionTool | cwl.Workflow, replace_etool: bool, inside: bool, skip_command_line1: bool, skip_command_line2: bool, ) -> tuple[cwl.CommandLineTool | cwl.ExpressionTool | cwl.Workflow, bool]: """Convert the given process and any subprocesses.""" match process: case cwl.CommandLineTool() if not inside: process = expand_stream_shortcuts(process) wf_inputs = [] wf_outputs = [] step_inputs = [] step_outputs = [] if process.inputs: for inp in process.inputs: inp_id = inp.id.split("#")[-1] step_inputs.append( cwl.WorkflowStepInput( id=inp_id, source=inp_id, extension_fields=inp.extension_fields, loadingOptions=inp.loadingOptions, ) ) wf_inputs.append( cwl.WorkflowInputParameter( id=inp_id, label=inp.label, secondaryFiles=inp.secondaryFiles, streamable=inp.streamable, doc=inp.doc, format=inp.format, default=inp.default, type_=inp.type_, extension_fields=inp.extension_fields, loadingOptions=inp.loadingOptions, ) ) if process.outputs: for outp in process.outputs: outp_id = outp.id.split("#")[-1] step_outputs.append(outp_id) wf_outputs.append( cwl.WorkflowOutputParameter( id=outp_id, label=outp.label, secondaryFiles=outp.secondaryFiles, streamable=outp.streamable, doc=outp.doc, format=outp.format, outputSource=f"main/{outp_id}", type_=outp.type_, extension_fields=outp.extension_fields, loadingOptions=outp.loadingOptions, ) ) step = cwl.WorkflowStep( id="#main", in_=step_inputs, out=step_outputs, run=copy.deepcopy(process), ) workflow = cwl.Workflow( inputs=wf_inputs, outputs=wf_outputs, steps=[step], cwlVersion=process.cwlVersion, ) result, modified = traverse_workflow( workflow, replace_etool, skip_command_line1, skip_command_line2 ) if modified: return result, True else: return process, False case cwl.ExpressionTool() if replace_etool: expression = get_expression(process.expression, empty_inputs(process), None) # Why call get_expression on an ExpressionTool? # It normalizes the form of $() CWL expressions into the ${} style if expression: process2 = copy.deepcopy(process) process2.expression = expression else: process2 = process return etool_to_cltool(process2), True case cwl.Workflow(): return traverse_workflow( process, replace_etool, skip_command_line1, skip_command_line2 ) case _: return process, False def load_step( step: cwl.WorkflowStep, replace_etool: bool, skip_command_line1: bool, skip_command_line2: bool, ) -> bool: """If the step's Process is not inline, load and process it.""" modified = False if isinstance(step.run, str): step.run, modified = traverse( cwl.load_document(step.run, baseuri=step.loadingOptions.fileuri), replace_etool, True, skip_command_line1, skip_command_line2, ) return modified def generate_etool_from_expr( expr: str, target: cwl.CommandInputParameter | cwl.WorkflowInputParameter, no_inputs: bool = False, self_type: None | ( cwl.WorkflowInputParameter | cwl.CommandInputParameter | list[cwl.WorkflowInputParameter | cwl.CommandInputParameter] ) = None, # if the "self" input should be a different type than the "result" output extra_processes: None | ( Sequence[cwl.Workflow | cwl.WorkflowStep | cwl.CommandLineTool] ) = None, ) -> cwl.ExpressionTool: """Convert a CWL Expression into an ExpressionTool.""" inputs = yaml.comments.CommentedSeq() if not no_inputs: if not self_type: self_type = target if isinstance(self_type, list): new_type: ( list[cwl.ArraySchema | cwl.InputRecordSchema] | cwl.ArraySchema | cwl.InputRecordSchema ) = [clean_type_ids(t.type_) for t in self_type] else: new_type = clean_type_ids(self_type.type_) inputs.append( cwl.WorkflowInputParameter( id="self", label=self_type.label if not isinstance(self_type, list) else None, secondaryFiles=( self_type.secondaryFiles if not isinstance(self_type, list) else None ), streamable=( self_type.streamable if not isinstance(self_type, list) else None ), doc=self_type.doc if not isinstance(self_type, list) else None, format=self_type.format if not isinstance(self_type, list) else None, type_=new_type, extension_fields=( self_type.extension_fields if not isinstance(self_type, list) else None ), loadingOptions=( self_type.loadingOptions if not isinstance(self_type, list) else None ), ) ) outputs = yaml.comments.CommentedSeq() outputs.append( cwl.ExpressionToolOutputParameter( id="result", label=target.label, secondaryFiles=target.secondaryFiles, streamable=target.streamable, doc=target.doc, format=target.format, type_=target.type_, extension_fields=target.extension_fields, loadingOptions=target.loadingOptions, ) ) expression = "${" if not no_inputs: expression += "\n var self=inputs.self;" expression += ( """ return {"result": function(){""" + expr[2:-2] + """}()}; }""" ) inlineJSReq = cwl.InlineJavascriptRequirement( find_expressionLib(extra_processes) if extra_processes else None ) return cwl.ExpressionTool( id="_:" + str(uuid.uuid4()), inputs=inputs, outputs=outputs, expression=expression, requirements=[inlineJSReq], cwlVersion="v1.0", ) def get_input_for_id( name: str, tool: cwl.CommandLineTool | cwl.Workflow ) -> cwl.CommandInputParameter | None: """Determine the CommandInputParameter for the given input name.""" name = name.split("/")[-1] for inp in cast(list[cwl.CommandInputParameter], tool.inputs): if inp.id and inp.id.split("#")[-1].split("/")[-1] == name: return inp if isinstance(tool, cwl.Workflow) and "/" in name: stepname, stem = name.split("/", 1) for step in tool.steps: if step.id == stepname: result = get_input_for_id(stem, step.run) if result: return result return None def find_expressionLib( processes: Sequence[ cwl.CommandLineTool | cwl.Workflow | cwl.ExpressionTool | cwl.WorkflowStep ], ) -> list[str] | None: """ Return the expressionLib from the highest priority InlineJavascriptRequirement. processes: should be in order of least important to most important (Workflow, WorkflowStep, ... CommandLineTool/ExpressionTool) """ for process in reversed(copy.copy(processes)): if process.requirements: for req in process.requirements: if isinstance(req, cwl.InlineJavascriptRequirement): return cast(list[str] | None, copy.deepcopy(req.expressionLib)) return None def replace_expr_with_etool( expr: str, name: str, workflow: cwl.Workflow, target: cwl.CommandInputParameter | cwl.WorkflowInputParameter, source: str | list[Any] | None, replace_etool: bool = False, extra_process: None | ( cwl.Workflow | cwl.WorkflowStep | cwl.CommandLineTool ) = None, source_type: cwl.CommandInputParameter | None = None, ) -> None: """Modify the given workflow, replacing the expr with an standalone ExpressionTool.""" extra_processes: list[cwl.Workflow | cwl.WorkflowStep | cwl.CommandLineTool] = [ workflow ] if extra_process: extra_processes.append(extra_process) etool: cwl.ExpressionTool = generate_etool_from_expr( expr, target, source is None, source_type, extra_processes ) if replace_etool: processes: list[cwl.WorkflowStep | cwl.Workflow | cwl.CommandLineTool] = [ workflow ] if extra_process: processes.append(extra_process) final_tool: cwl.ExpressionTool | cwl.CommandLineTool = etool_to_cltool( etool, find_expressionLib(processes) ) else: final_tool = etool inps = [] if source: inps.append(cwl.WorkflowStepInput(id="self", source=source)) workflow.steps.append( cwl.WorkflowStep( id=name, in_=inps, out=[cwl.WorkflowStepOutput("result")], run=final_tool, ) ) def replace_wf_input_ref_with_step_output( workflow: cwl.Workflow, name: str, target: str ) -> None: """Refactor all reference to a workflow input to the specified step output.""" if workflow.steps: for step in workflow.steps: if step.in_: for inp in step.in_: if inp.source: if inp.source == name: inp.source = target if isinstance(inp.source, MutableSequence): for index, source in enumerate(inp.source): if source == name: inp.source[index] = target if workflow.outputs: for outp in workflow.outputs: if outp.outputSource: if outp.outputSource == name: outp.outputSource = target if isinstance(outp.outputSource, MutableSequence): for index, outputSource in enumerate(outp.outputSource): if outputSource == name: outp.outputSource[index] = target def empty_inputs( process_or_step: ( cwl.CommandLineTool | cwl.WorkflowStep | cwl.ExpressionTool | cwl.Workflow ), parent: cwl.Workflow | None = None, ) -> dict[str, Any]: """Produce a mock input object for the given inputs.""" result = {} if isinstance(process_or_step, cwl.Process): for param in process_or_step.inputs: result[param.id.split("#")[-1]] = example_input(param.type_) else: for param in process_or_step.in_: param_id = param.id.split("/")[-1] if param.source is None and param.valueFrom: result[param_id] = example_input("string") elif param.source is None and param.default: result[param_id] = param.default else: with suppress(WorkflowException): result[param_id] = example_input( utils.type_for_source(process_or_step.run, param.source, parent) ) return result def example_input(some_type: Any) -> Any: """Produce a fake input for the given type.""" # TODO: accept some sort of context object with local custom type definitions if some_type == "Directory": return CWLDirectoryType( **{ "class": "Directory", "location": "https://www.example.com/example", "basename": "example", "listing": [ CWLFileType( **{ "class": "File", "basename": "example.txt", "size": 23, "contents": "hoopla", "nameroot": "example", "nameext": "txt", } ) ], } ) if some_type == "File": return CWLFileType( **{ "class": "File", "location": "https://www.example.com/example.txt", "basename": "example.txt", "size": 23, "contents": "hoopla", "nameroot": "example", "nameext": "txt", } ) if some_type == "int": return 23 if some_type == "string": return "hoopla!" if some_type == "boolean": return True return None EMPTY_FILE = CWLFileType( **{ "class": "File", "basename": "em.pty", "nameroot": "em", "nameext": "pty", } ) TOPLEVEL_SF_EXPR_ERROR = ( "Input '{}'. Sorry, CWL Expressions as part of a secondaryFiles " "specification in a Workflow level input or standalone CommandLine Tool " "are not able to be refactored into separate ExpressionTool or " "CommandLineTool steps." ) TOPLEVEL_FORMAT_EXPR_ERROR = ( "Input '{}'. Sorry, CWL Expressions as part of a format " "specification in a Workflow level input are not able to be refactored " "into separate ExpressionTool/CommandLineTool steps." ) PICKVALUE_FIRST_NON_NULL_EXPR = """${ for (let i = 0; i < self.length; i++) { if (self[i] !== null){ return self[i]; } } throw 'pickValue=first_non_null, but no non-null value found: ' + self; } """ PICKVALUE_THE_ONLY_NON_NULL_EXPR = """${ var found = null; self.forEach(function(item) { if (item !== null) { if (found !== null) { throw 'pickValue=the_only_non_null, but multiple non-null values found: ' + self; } else { found = item; } } }) if (found !== null) { return found; } throw 'pickValue=the_only_non_null, but no non-null value found: ' + self; } """ PICKVALUE_ALL_NON_NULL_EXPR = """${ var results = []; self.forEach(function(item) { if (item !== null){ results.push(item); } }) return results; } """ PICKVALUE_ERROR = ( "pickValue '{}' is invalid. Should be one of 'first_non_null', " "'the_only_non_null', 'all_non_null'" ) def process_workflow_inputs_and_outputs( workflow: cwl.Workflow, replace_etool: bool ) -> bool: """Do any needed conversions on the given Workflow's inputs and outputs.""" modified = False inputs = empty_inputs(workflow) for index, param in enumerate(workflow.inputs): with SourceLine(workflow.inputs, index, WorkflowException): if param.format and get_expression(param.format, inputs, None): raise SourceLine( param.loadingOptions.original_doc, "format", raise_type=WorkflowException, ).makeError(TOPLEVEL_FORMAT_EXPR_ERROR.format(param.id.split("#")[-1])) if param.secondaryFiles: if hasattr(param.secondaryFiles, "pattern") and get_expression( param.secondaryFiles.pattern, inputs, EMPTY_FILE ): raise SourceLine( param.loadingOptions.original_doc, "secondaryFiles", raise_type=WorkflowException, ).makeError(TOPLEVEL_SF_EXPR_ERROR.format(param.id.split("#")[-1])) elif isinstance(param.secondaryFiles, MutableSequence): for index2, entry in enumerate(param.secondaryFiles): if get_expression(entry.pattern, inputs, EMPTY_FILE): raise SourceLine( param.loadingOptions.original_doc, index2, raise_type=WorkflowException, ).makeError( f"Entry {index}," + TOPLEVEL_SF_EXPR_ERROR.format(param.id.split("#")[-1]) ) generated_pickValue_steps = [] for index3, param2 in enumerate(workflow.outputs): with SourceLine(workflow.outputs, index3, WorkflowException): if param2.pickValue: if param2.pickValue == "first_non_null": expression = PICKVALUE_FIRST_NON_NULL_EXPR elif param2.pickValue == "the_only_non_null": expression = PICKVALUE_THE_ONLY_NON_NULL_EXPR elif param2.pickValue == "all_non_null": expression = PICKVALUE_ALL_NON_NULL_EXPR else: raise WorkflowException(PICKVALUE_ERROR.format(param2.pickValue)) modified = True etool_id = "_pickValue_workflow_step_{}".format( param2.id.split("#")[-1] ) target_type = copy.deepcopy(param2.type_) if isinstance(target_type, cwl.OutputArraySchema): target_type.name = "" target = cwl.WorkflowInputParameter(id=None, type_=target_type) if not isinstance(param2.outputSource, list): sources = param2.outputSource.split("#")[-1] else: sources = [s.split("#")[-1] for s in param2.outputSource] source_type_items = utils.type_for_source(workflow, sources) if isinstance(source_type_items, cwl.ArraySchema): if isinstance(source_type_items.items, list): if "null" not in source_type_items.items: source_type_items.items.append("null") elif source_type_items.items != "null": source_type_items.items = ["null", source_type_items.items] elif isinstance(source_type_items, list): if "null" not in source_type_items: source_type_items.append("null") elif source_type_items != "null": source_type_items = ["null", source_type_items] source_type = cwl.CommandInputParameter( id=None, type_=source_type_items ) replace_expr_with_etool( expression, etool_id, workflow, target, sources, replace_etool, None, source_type, ) param2.outputSource = f"{etool_id}/result" param2.pickValue = None generated_pickValue_steps.append(etool_id) return modified def process_workflow_reqs_and_hints( workflow: cwl.Workflow, replace_etool: bool ) -> bool: """ Convert any expressions in a workflow's reqs and hints. Each expression will be converted to an additional step. The converted requirement will be copied to all workflow steps that don't have that requirement type. Those affected steps will gain an additional input from the relevant synthesized expression step. """ # TODO: consolidate the generated etools/cltools into a single "_expression_workflow_reqs" step # TODO: support resourceReq.* references to Workflow.inputs? # ^ By refactoring replace_expr_etool to allow multiple inputs, # and connecting all workflow inputs to the generated step modified = False inputs = empty_inputs(workflow) generated_res_reqs: list[tuple[str, int | str]] = [] generated_iwdr_reqs: list[tuple[str, int | str]] = [] generated_envVar_reqs: list[tuple[str, int | str]] = [] prop_reqs: tuple[ ( type[cwl.EnvVarRequirement] | type[cwl.ResourceRequirement] | type[cwl.InitialWorkDirRequirement] ), ..., ] = () resourceReq: cwl.ResourceRequirement | None = None envVarReq: cwl.EnvVarRequirement | None = None iwdr: cwl.InitialWorkDirRequirement | None = None if workflow.requirements is not None: for req in cast(list[cwl.ProcessRequirement], workflow.requirements): match req: case cwl.EnvVarRequirement() if req.envDef: for index, envDef in enumerate(req.envDef): if envDef.envValue: expression = get_expression(envDef.envValue, inputs, None) if expression: modified = True target = cwl.WorkflowInputParameter( id=None, type_="string", ) etool_id = ( "_expression_workflow_EnvVarRequirement_{}".format( index ) ) replace_expr_with_etool( expression, etool_id, workflow, target, None, replace_etool, ) if envVarReq is None: envVarReq = copy.deepcopy(req) prop_reqs += (cwl.EnvVarRequirement,) newEnvDef = copy.deepcopy(envDef) newEnvDef.envValue = f"$(inputs._envDef{index})" envVarReq.envDef[index] = newEnvDef generated_envVar_reqs.append((etool_id, index)) case cwl.ResourceRequirement(): for attr in cwl.ResourceRequirement.attrs: this_attr = getattr(req, attr, None) if this_attr: expression = get_expression(this_attr, inputs, None) if expression: modified = True target = cwl.WorkflowInputParameter( id=None, type_="long" ) etool_id = "_expression_workflow_ResourceRequirement_{}".format( attr ) replace_expr_with_etool( expression, etool_id, workflow, target, None, replace_etool, ) if not resourceReq: resourceReq = cwl.ResourceRequirement( loadingOptions=workflow.loadingOptions, ) prop_reqs += (cwl.ResourceRequirement,) setattr(resourceReq, attr, f"$(inputs._{attr})") generated_res_reqs.append((etool_id, attr)) case cwl.InitialWorkDirRequirement() if req.listing: if isinstance(req.listing, str): expression = get_expression(req.listing, inputs, None) if expression: modified = True target = cwl.WorkflowInputParameter( id=None, type_=cwl.InputArraySchema( ["File", "Directory"], "array", None, None ), ) etool_id = "_expression_workflow_InitialWorkDirRequirement" replace_expr_with_etool( expression, etool_id, workflow, target, None, replace_etool, ) iwdr = cwl.InitialWorkDirRequirement( listing="$(inputs._iwdr_listing)", loadingOptions=workflow.loadingOptions, ) prop_reqs += (cwl.InitialWorkDirRequirement,) else: iwdr = copy.deepcopy(req) for index, entry in enumerate(req.listing): expression = get_expression(entry, inputs, None) if expression: modified = True target = cwl.WorkflowInputParameter( id=None, type_=cwl.InputArraySchema( ["File", "Directory"], "array", None, None ), ) etool_id = "_expression_workflow_InitialWorkDirRequirement_{}".format( index ) replace_expr_with_etool( expression, etool_id, workflow, target, None, replace_etool, ) iwdr.listing[index] = f"$(inputs._iwdr_listing_{index}" generated_iwdr_reqs.append((etool_id, index)) elif isinstance(entry, cwl.Dirent): if entry.entry: expression = get_expression( entry.entry, inputs, None ) if expression: expr: str = expression expr_result = do_eval( ex=entry.entry, jobinput=inputs, requirements=[], outdir="", tmpdir="", resources={}, ) modified = True if ( isinstance(expr_result, Mapping) and "class" in expr_result and ( expr_result["class"] in ("File", "Directory") ) ): target = cwl.WorkflowInputParameter( id=None, type_=expr_result["class"], ) replace_expr_with_etool( expr, etool_id, workflow, target, None, replace_etool, ) iwdr.listing[index] = ( "$(inputs._iwdr_listing_{}".format( index ) ) generated_iwdr_reqs.append( (etool_id, index) ) elif isinstance(expr_result, str): target = cwl.WorkflowInputParameter( id=None, type_=["File"], ) if entry.entryname is None: raise SourceLine( entry.loadingOptions.original_doc, index, raise_type=WorkflowException, ).makeError( f"Entry {index}," + "Invalid CWL, if 'entry' " "is a string, then entryName must be specified." ) expr = ( '${return {"class": "File", "basename": "' + entry.entryname + '", "contents": (function(){' + expr[2:-1] + "})() }; }" ) etool_id = "_expression_workflow_InitialWorkDirRequirement_{}".format( index ) replace_expr_with_etool( expr, etool_id, workflow, target, None, replace_etool, ) iwdr.listing[index] = ( f"$(inputs._iwdr_listing_{index}" ) generated_iwdr_reqs.append((etool_id, index)) elif entry.entryname: expression = get_expression( entry.entryname, inputs, None ) if expression: modified = True target = cwl.WorkflowInputParameter( id=None, type_="string", ) etool_id = "_expression_workflow_InitialWorkDirRequirement_{}".format( index ) replace_expr_with_etool( expression, etool_id, workflow, target, None, replace_etool, ) iwdr.listing[index] = ( f"$(inputs._iwdr_listing_{index}" ) generated_iwdr_reqs.append((etool_id, index)) if generated_iwdr_reqs: prop_reqs += (cwl.InitialWorkDirRequirement,) else: iwdr = None if envVarReq and workflow.steps: for step in workflow.steps: if step.id.split("#")[-1].startswith("_expression_"): continue if step.requirements: for req in step.requirements: if isinstance(req, cwl.EnvVarRequirement): continue else: step.requirements = yaml.comments.CommentedSeq() step.requirements.append(envVarReq) for entry in generated_envVar_reqs: step.in_.append( cwl.WorkflowStepInput( id=f"_envDef{entry[1]}", source=f"{entry[0]}/result", ) ) if resourceReq and workflow.steps: for step in workflow.steps: if step.id.split("#")[-1].startswith("_expression_"): continue if step.requirements: for req in step.requirements: if isinstance(req, cwl.ResourceRequirement): continue else: step.requirements = yaml.comments.CommentedSeq() step.requirements.append(resourceReq) for entry in generated_res_reqs: step.in_.append( cwl.WorkflowStepInput( id=f"_{entry[1]}", source=f"{entry[0]}/result", ) ) if iwdr and workflow.steps: for step in workflow.steps: if step.id.split("#")[-1].startswith("_expression_"): continue if step.requirements: for req in step.requirements: if isinstance(req, cwl.InitialWorkDirRequirement): continue else: step.requirements = yaml.comments.CommentedSeq() step.requirements.append(iwdr) if generated_iwdr_reqs: for entry in generated_iwdr_reqs: step.in_.append( cwl.WorkflowStepInput( id=f"_iwdr_listing_{index}", source=f"{entry[0]}/result", ) ) else: step.in_.append( cwl.WorkflowStepInput( id="_iwdr_listing", source="_expression_workflow_InitialWorkDirRequirement/result", ) ) if workflow.requirements: workflow.requirements[:] = [ x for x in workflow.requirements if not isinstance(x, prop_reqs) ] return modified def process_level_reqs( process: cwl.CommandLineTool, step: cwl.WorkflowStep, parent: cwl.Workflow, replace_etool: bool, skip_command_line1: bool, skip_command_line2: bool, ) -> bool: """Convert expressions inside a process into new adjacent steps.""" # This is for reqs inside a Process (CommandLineTool, ExpressionTool) # differences from process_workflow_reqs_and_hints() are: # - the name of the generated ETools/CTools contains the name of the step, not "workflow" # - Generated ETools/CTools are adjacent steps # - Replace the CWL Expression inplace with a CWL parameter reference # - Don't create a new Requirement, nor delete the existing Requirement # - the Process is passed to replace_expr_with_etool for later searching for JS expressionLibs # - in addition to adding the input to the step for the ETool/CTool result, # add it to the Process.inputs as well if not process.requirements: return False modified = False target_process = step.run inputs = empty_inputs(process) generated_res_reqs: list[tuple[str, str]] = [] generated_iwdr_reqs: list[tuple[str, int | str, Any]] = [] generated_envVar_reqs: list[tuple[str, int | str]] = [] if not step.id: return False step_name = step.id.split("#", 1)[-1] for req_index, req in enumerate(process.requirements): match req: case cwl.EnvVarRequirement() if req.envDef: for env_index, envDef in enumerate(req.envDef): if envDef.envValue: expression = get_expression(envDef.envValue, inputs, None) if expression: modified = True target = cwl.WorkflowInputParameter(id=None, type_="string") etool_id = "_expression_{}_EnvVarRequirement_{}".format( step_name, env_index ) replace_expr_with_etool( expression, etool_id, parent, target, None, replace_etool, process, ) target_process.requirements[req_index][ env_index ].envValue = f"$(inputs._envDef{env_index})" generated_envVar_reqs.append((etool_id, env_index)) case cwl.ResourceRequirement(): for attr in cwl.ResourceRequirement.attrs: this_attr = getattr(req, attr, None) if this_attr: expression = get_expression(this_attr, inputs, None) if expression: modified = True target = cwl.WorkflowInputParameter(id=None, type_="long") etool_id = "_expression_{}_ResourceRequirement_{}".format( step_name, attr ) replace_clt_hintreq_expr_with_etool( expression, etool_id, parent, target, step, replace_etool, ) setattr( target_process.requirements[req_index], attr, f"$(inputs._{attr})", ) generated_res_reqs.append((etool_id, attr)) case cwl.InitialWorkDirRequirement() if ( not skip_command_line2 and req.listing ): if isinstance(req.listing, str): expression = get_expression(req.listing, inputs, None) if expression: modified = True target_type = cwl.InputArraySchema( ["File", "Directory"], "array", None, None ) target = cwl.WorkflowInputParameter(id=None, type_=target_type) etool_id = "_expression_{}_InitialWorkDirRequirement".format( step_name ) replace_expr_with_etool( expression, etool_id, parent, target, None, replace_etool, process, ) target_process.requirements[req_index].listing = ( "$(inputs._iwdr_listing)", ) step.in_.append( cwl.WorkflowStepInput( id="_iwdr_listing", source=f"{etool_id}/result", ) ) add_input_to_process( target_process, "_iwdr_listing", target_type, process.loadingOptions, ) else: for listing_index, entry in enumerate(req.listing): expression = get_expression(entry, inputs, None) if expression: modified = True target_type = cwl.InputArraySchema( ["File", "Directory"], "array", None, None ) target = cwl.WorkflowInputParameter( id=None, type_=target_type, ) etool_id = ( "_expression_{}_InitialWorkDirRequirement_{}".format( step_name, listing_index ) ) replace_expr_with_etool( expression, etool_id, parent, target, None, replace_etool, process, ) target_process.requirements[req_index].listing[ listing_index ] = f"$(inputs._iwdr_listing_{listing_index}" generated_iwdr_reqs.append( (etool_id, listing_index, target_type) ) elif isinstance(entry, cwl.Dirent): if entry.entry: expression = get_expression(entry.entry, inputs, None) if expression: modified = True if entry.entryname is not None: entryname_expr = get_expression( entry.entryname, inputs, None ) entryname = ( entry.entryname if entryname_expr else f'"{entry.entryname}"' # noqa: B907 ) new_expression = ( "${var result; var entryname = " + entryname + "; var entry = " + entry.entry[2:-1] + """; if (typeof entry === 'string' || entry instanceof String) { result = {"class": "File", "basename": entryname, "contents": entry} ; if (typeof entryname === 'string' || entryname instanceof String) { result.basename = entryname ; } } else { result = entry ; } return result; }""" ) else: new_expression = expression d_target_type = ["File", "Directory"] target = cwl.WorkflowInputParameter( id=None, type_=d_target_type, ) etool_id = "_expression_{}_InitialWorkDirRequirement_{}".format( step_name, listing_index ) replace_clt_hintreq_expr_with_etool( new_expression, etool_id, parent, target, step, replace_etool, ) target_process.requirements[req_index].listing[ listing_index ].entry = "$(inputs._iwdr_listing_{})".format( listing_index ) generated_iwdr_reqs.append( (etool_id, listing_index, d_target_type) ) elif entry.entryname: expression = get_expression( entry.entryname, inputs, None ) if expression: modified = True target = cwl.WorkflowInputParameter( id=None, type_="string", ) etool_id = "_expression_{}_InitialWorkDirRequirement_{}".format( step_name, listing_index ) replace_expr_with_etool( expression, etool_id, parent, target, None, replace_etool, process, ) target_process.requirements[req_index].listing[ listing_index ].entryname = "$(inputs._iwdr_listing_{})".format( listing_index ) generated_iwdr_reqs.append( (etool_id, listing_index, "string") ) for entry in generated_envVar_reqs: name = f"_envDef{entry[1]}" step.in_.append(cwl.WorkflowStepInput(id=name, source=f"{entry[0]}/result")) add_input_to_process(target_process, name, "string", process.loadingOptions) for entry in generated_res_reqs: name = f"_{entry[1]}" step.in_.append(cwl.WorkflowStepInput(id=name, source=f"{entry[0]}/result")) add_input_to_process(target_process, name, "long", process.loadingOptions) for entry in generated_iwdr_reqs: name = f"_iwdr_listing_{entry[1]}" step.in_.append(cwl.WorkflowStepInput(id=name, source=f"{entry[0]}/result")) add_input_to_process(target_process, name, entry[2], process.loadingOptions) return modified def add_input_to_process( process: cwl.Process, name: str, inptype: Any, loadingOptions: cwl.LoadingOptions ) -> None: """Add a new InputParameter to the given CommandLineTool.""" if isinstance(process, cwl.CommandLineTool): process.inputs.append( cwl.CommandInputParameter( id=name, type_=inptype, loadingOptions=loadingOptions, ) ) def traverse_CommandLineTool( clt: cwl.CommandLineTool, parent: cwl.Workflow, step: cwl.WorkflowStep, replace_etool: bool, skip_command_line1: bool, skip_command_line2: bool, ) -> bool: """Extract any CWL Expressions within the given CommandLineTool into sibling steps.""" modified = False # don't modify clt, modify step.run target_clt = step.run inputs = empty_inputs(clt) if not step.id: return False step_id = step.id.split("#")[-1] if clt.arguments and not skip_command_line1: for index, arg in enumerate(clt.arguments): if isinstance(arg, str): expression = get_expression(arg, inputs, None) if expression: modified = True inp_id = f"_arguments_{index}" etool_id = f"_expression_{step_id}{inp_id}" target_type = "Any" target = cwl.WorkflowInputParameter(id=None, type_=target_type) replace_step_clt_expr_with_etool( expression, etool_id, parent, target, step, replace_etool ) target_clt.arguments[index] = cwl.CommandLineBinding( valueFrom=f"$(inputs.{inp_id})" ) target_clt.inputs.append( cwl.CommandInputParameter( id=inp_id, type_=target_type, ) ) step.in_.append( cwl.WorkflowStepInput( f"{etool_id}/result", None, inp_id, None, None ) ) remove_JSReq(target_clt, skip_command_line1) elif isinstance(arg, cwl.CommandLineBinding) and arg.valueFrom: expression = get_expression(arg.valueFrom, inputs, None) if expression: modified = True inp_id = f"_arguments_{index}" etool_id = f"_expression_{step_id}{inp_id}" target_type = "Any" target = cwl.WorkflowInputParameter(id=None, type_=target_type) replace_step_clt_expr_with_etool( expression, etool_id, parent, target, step, replace_etool ) target_clt.arguments[index].valueFrom = "$(inputs.{})".format( inp_id ) target_clt.inputs.append( cwl.CommandInputParameter( id=inp_id, type_=target_type, ) ) step.in_.append( cwl.WorkflowStepInput(id=inp_id, source=f"{etool_id}/result") ) remove_JSReq(target_clt, skip_command_line1) for streamtype in "stdout", "stderr": # add 'stdin' for v1.1 version stream_value = getattr(clt, streamtype) if stream_value: expression = get_expression(stream_value, inputs, None) if expression: modified = True inp_id = f"_{streamtype}" etool_id = f"_expression_{step_id}{inp_id}" target_type = "string" target = cwl.WorkflowInputParameter(id=None, type_=target_type) replace_step_clt_expr_with_etool( expression, etool_id, parent, target, step, replace_etool ) setattr(target_clt, streamtype, f"$(inputs.{inp_id})") target_clt.inputs.append( cwl.CommandInputParameter(id=inp_id, type_=target_type) ) step.in_.append( cwl.WorkflowStepInput(id=inp_id, source=f"{etool_id}/result") ) for inp in clt.inputs: if not skip_command_line1 and inp.inputBinding and inp.inputBinding.valueFrom: expression = get_expression( inp.inputBinding.valueFrom, inputs, example_input(inp.type_) ) if expression: modified = True self_id = inp.id.split("#")[-1] inp_id = f"_{self_id}_valueFrom" etool_id = f"_expression_{step_id}{inp_id}" replace_step_clt_expr_with_etool( expression, etool_id, parent, inp, step, replace_etool, self_id ) inp.inputBinding.valueFrom = f"$(inputs.{inp_id})" target_clt.inputs.append( cwl.CommandInputParameter(id=inp_id, type_=inp.type_) ) step.in_.append( cwl.WorkflowStepInput(id=inp_id, source=f"{etool_id}/result") ) for outp in clt.outputs: if outp.outputBinding: if outp.outputBinding.glob: expression = get_expression(outp.outputBinding.glob, inputs, None) if expression: modified = True inp_id = "_{}_glob".format(outp.id.split("#")[-1]) etool_id = f"_expression_{step_id}{inp_id}" glob_target_type = ["string", cwl.ArraySchema("string", "array")] target = cwl.WorkflowInputParameter(id=None, type_=glob_target_type) replace_step_clt_expr_with_etool( expression, etool_id, parent, target, step, replace_etool ) outp.outputBinding.glob = f"$(inputs.{inp_id})" target_clt.inputs.append( cwl.CommandInputParameter( id=inp_id, type_=glob_target_type, ) ) step.in_.append( cwl.WorkflowStepInput(id=inp_id, source=f"{etool_id}/result") ) if outp.outputBinding.outputEval and not skip_command_line2: self: CWLOutputType = [ { "class": "File", "basename": "base.name", "nameroot": "base", "nameext": "name", "path": "/tmp/base.name", # nosec "dirname": "/tmp", # nosec } ] if outp.outputBinding.loadContents: cast(dict[Any, Any], self)[0]["contents"] = "stuff" expression = get_expression(outp.outputBinding.outputEval, inputs, self) if expression: modified = True outp_id = outp.id.split("#")[-1] inp_id = f"_{outp_id}_outputEval" etool_id = f"expression{inp_id}" sub_wf_outputs = cltool_step_outputs_to_workflow_outputs( step, etool_id, outp_id ) self_type = cwl.WorkflowInputParameter( id=None, type_=cwl.InputArraySchema("File", "array", None, None), ) etool = generate_etool_from_expr( expression, outp, False, self_type, [clt, step, parent] ) if outp.outputBinding.loadContents: etool.inputs[0].type_.inputBinding = cwl.CommandLineBinding( loadContents=True ) etool.inputs.extend(cltool_inputs_to_etool_inputs(clt)) sub_wf_inputs = cltool_inputs_to_etool_inputs(clt) orig_step_inputs = copy.deepcopy(step.in_) for orig_step_input in orig_step_inputs: orig_step_input.id = orig_step_input.id.split("/")[-1] if isinstance(orig_step_input.source, MutableSequence): for index, source in enumerate(orig_step_input.source): orig_step_input.source[index] = source.split("#")[-1] else: orig_step_input.source = orig_step_input.source.split("#")[ -1 ] orig_step_inputs[:] = [ x for x in orig_step_inputs if not x.id.startswith("_") ] for inp in orig_step_inputs: inp.source = inp.id inp.linkMerge = None if replace_etool: processes = [parent] final_etool: cwl.CommandLineTool | cwl.ExpressionTool = ( etool_to_cltool(etool, find_expressionLib(processes)) ) else: final_etool = etool etool_step = cwl.WorkflowStep( id=etool_id, in_=orig_step_inputs, out=[cwl.WorkflowStepOutput("result")], run=final_etool, scatterMethod=step.scatterMethod, ) new_clt_step = copy.copy( step ) # a deepcopy would be convenient, but params2.cwl gives it problems new_clt_step.id = new_clt_step.id.split("#")[-1] new_clt_step.run = copy.copy(step.run) new_clt_step.run.id = None remove_JSReq(new_clt_step.run, skip_command_line1) for new_outp in new_clt_step.run.outputs: if new_outp.id.split("#")[-1] == outp_id: if isinstance( new_outp, ( cwl.WorkflowOutputParameter, cwl.ExpressionToolOutputParameter, ), ): new_outp.type_ = cwl.OutputArraySchema( items="File", type_="array" ) elif isinstance(new_outp, cwl.CommandOutputParameter): if new_outp.outputBinding: new_outp.outputBinding.outputEval = None new_outp.outputBinding.loadContents = None new_outp.type_ = cwl.CommandOutputArraySchema( items="File", type_="array", ) else: raise Exception( "Unimplemented OutputParameter type: %s", type(new_outp), ) new_clt_step.in_ = copy.deepcopy(step.in_) for inp in new_clt_step.in_: inp.id = inp.id.split("/")[-1] inp.source = inp.id inp.linkMerge = None for index, out in enumerate(new_clt_step.out): new_clt_step.out[index] = out.split("/")[-1] for tool_inp in new_clt_step.run.inputs: tool_inp.id = tool_inp.id.split("#")[-1] for tool_out in new_clt_step.run.outputs: tool_out.id = tool_out.id.split("#")[-1] sub_wf_steps = [new_clt_step, etool_step] sub_workflow = cwl.Workflow( inputs=sub_wf_inputs, outputs=sub_wf_outputs, steps=sub_wf_steps, cwlVersion=parent.cwlVersion, ) if step.scatter: new_clt_step.scatter = None step.run = sub_workflow rename_step_source( sub_workflow, f"{step_id}/{outp_id}", f"{etool_id}/result", ) orig_step_inputs.append( cwl.WorkflowStepInput(id="self", source=f"{step_id}/{outp_id}") ) if not parent.requirements: parent.requirements = [cwl.SubworkflowFeatureRequirement()] else: has_sub_wf_req = False for req in parent.requirements: if isinstance(req, cwl.SubworkflowFeatureRequirement): has_sub_wf_req = True if not has_sub_wf_req: parent.requirements.append( cwl.SubworkflowFeatureRequirement() ) return modified def rename_step_source(workflow: cwl.Workflow, old: str, new: str) -> None: """Update step source names to the new name.""" def simplify_wf_id(uri: str) -> str: return uri.split("#")[-1].split("/", 1)[1] def simplify_step_id(uri: str) -> str: return uri.split("#")[-1] for wf_outp in workflow.outputs: if wf_outp.outputSource and simplify_wf_id(wf_outp.outputSource) == old: wf_outp.outputSource = new for step in workflow.steps: if step.in_: for inp in step.in_: if inp.source: if isinstance(inp.source, str): source_id = ( simplify_step_id(inp.source) if "#" in inp.source else inp.source ) if source_id == old: inp.source = new else: for index, source in enumerate(inp.source): if simplify_step_id(source) == old: inp.source[index] = new def remove_JSReq( process: cwl.CommandLineTool | cwl.WorkflowStep | cwl.Workflow, skip_command_line1: bool, ) -> None: """Since the InlineJavascriptRequirement is longer needed, remove it.""" if skip_command_line1 and isinstance(process, cwl.CommandLineTool): return if process.hints: process.hints[:] = [ hint for hint in process.hints if not isinstance(hint, cwl.InlineJavascriptRequirement) ] if not process.hints: process.hints = None if process.requirements: process.requirements[:] = [ req for req in process.requirements if not isinstance(req, cwl.InlineJavascriptRequirement) ] if not process.requirements: process.requirements = None def replace_step_clt_expr_with_etool( expr: str, name: str, workflow: cwl.Workflow, target: cwl.WorkflowInputParameter, step: cwl.WorkflowStep, replace_etool: bool, self_name: str | None = None, ) -> None: """Convert a step level CWL Expression to a sibling expression step.""" etool_inputs = cltool_inputs_to_etool_inputs(step.run) temp_etool = generate_etool_from_expr2( expr, target, etool_inputs, self_name, step.run, [workflow] ) if replace_etool: processes = [workflow] etool: cwl.ExpressionTool | cwl.CommandLineTool = etool_to_cltool( temp_etool, find_expressionLib(processes) ) else: etool = temp_etool wf_step_inputs = copy.deepcopy(step.in_) for wf_step_input in wf_step_inputs: wf_step_input.id = wf_step_input.id.split("/")[-1] wf_step_inputs[:] = [x for x in wf_step_inputs if not x.id.startswith("_")] workflow.steps.append( cwl.WorkflowStep( id=name, in_=wf_step_inputs, out=[cwl.WorkflowStepOutput("result")], run=etool, ) ) def replace_clt_hintreq_expr_with_etool( expr: str, name: str, workflow: cwl.Workflow, target: cwl.WorkflowInputParameter, step: cwl.WorkflowStep, replace_etool: bool, self_name: str | None = None, ) -> cwl.CommandLineTool | cwl.ExpressionTool: """Factor out an expression inside a CommandLineTool req or hint into a sibling step.""" # Same as replace_step_clt_expr_with_etool or different? etool_inputs = cltool_inputs_to_etool_inputs(step.run) temp_etool = generate_etool_from_expr2( expr, target, etool_inputs, self_name, step.run, [workflow] ) if replace_etool: processes = [workflow] etool: cwl.CommandLineTool | cwl.ExpressionTool = etool_to_cltool( temp_etool, find_expressionLib(processes) ) else: etool = temp_etool wf_step_inputs = copy.deepcopy(step.in_) for wf_step_input in wf_step_inputs: wf_step_input.id = wf_step_input.id.split("/")[-1] wf_step_inputs[:] = [x for x in wf_step_inputs if not x.id.startswith("_")] workflow.steps.append( cwl.WorkflowStep( id=name, in_=wf_step_inputs, out=[cwl.WorkflowStepOutput("result")], run=etool, ) ) return etool def cltool_inputs_to_etool_inputs( tool: cwl.CommandLineTool, ) -> list[cwl.WorkflowInputParameter]: """Copy CommandLineTool input objects into the equivalent ExpressionTool input objects.""" inputs = yaml.comments.CommentedSeq() if tool.inputs: for clt_inp in tool.inputs: clt_inp_id = clt_inp.id.split("#")[-1].split("/")[-1] if not clt_inp_id.startswith("_"): inputs.append( cwl.WorkflowInputParameter( id=clt_inp_id, label=clt_inp.label, secondaryFiles=clt_inp.secondaryFiles, streamable=clt_inp.streamable, doc=clt_inp.doc, format=clt_inp.format, default=clt_inp.default, type_=clt_inp.type_, extension_fields=clt_inp.extension_fields, loadingOptions=clt_inp.loadingOptions, ) ) return inputs def cltool_step_outputs_to_workflow_outputs( cltool_step: cwl.WorkflowStep, etool_step_id: str, etool_out_id: str ) -> list[cwl.OutputParameter]: """ Copy CommandLineTool outputs into the equivalent Workflow output parameters. Connects the outputSources for each of the new output parameters to the step they came from. """ outputs = yaml.comments.CommentedSeq() if not cltool_step.id: raise WorkflowException(f"Missing step id from {cltool_step}.") default_step_id = cltool_step.id.split("#")[-1] if cltool_step.run.outputs: for clt_out in cltool_step.run.outputs: clt_out_id = clt_out.id.split("#")[-1].split("/")[-1] if clt_out_id == etool_out_id: outputSource = f"{etool_step_id}/result" else: outputSource = f"{default_step_id}/{clt_out_id}" if not clt_out_id.startswith("_"): outputs.append( cwl.WorkflowOutputParameter( id=clt_out_id, label=clt_out.label, secondaryFiles=clt_out.secondaryFiles, streamable=clt_out.streamable, doc=clt_out.doc, format=clt_out.format, outputSource=outputSource, type_=clt_out.type_, extension_fields=clt_out.extension_fields, loadingOptions=clt_out.loadingOptions, ) ) return outputs def generate_etool_from_expr2( expr: str, target: cwl.CommandInputParameter | cwl.WorkflowInputParameter, inputs: Sequence[ cwl.WorkflowInputParameter | cwl.CommandInputParameter | cwl.CommandOutputParameter ], self_name: str | None = None, process: cwl.CommandLineTool | cwl.ExpressionTool | None = None, extra_processes: None | ( Sequence[cwl.Workflow | cwl.WorkflowStep | cwl.CommandLineTool] ) = None, ) -> cwl.ExpressionTool: """Generate an ExpressionTool to achieve the same result as the given expression.""" outputs = yaml.comments.CommentedSeq() outputs.append( cwl.ExpressionToolOutputParameter( id="result", label=target.label, secondaryFiles=target.secondaryFiles, streamable=target.streamable, doc=target.doc, format=target.format, type_=target.type_, ) ) expression = "${" if self_name: expression += f"\n var self=inputs.{self_name};" expression += ( """ return {"result": function(){""" + expr[2:-2] + """}()}; }""" ) hints = None procs: list[ cwl.CommandLineTool | cwl.ExpressionTool | cwl.Workflow | cwl.WorkflowStep ] = [] if process: procs.append(process) if extra_processes: procs.extend(extra_processes) inlineJSReq = cwl.InlineJavascriptRequirement(find_expressionLib(procs)) reqs = [inlineJSReq] if process: if process.hints: hints = copy.deepcopy(process.hints) hints[:] = [ x for x in hints if not isinstance(x, cwl.InitialWorkDirRequirement) ] if process.requirements: reqs.extend(copy.deepcopy(process.requirements)) reqs[:] = [ x for x in reqs if not isinstance(x, cwl.InitialWorkDirRequirement) ] return cwl.ExpressionTool( id="_:" + str(uuid.uuid4()), inputs=inputs, outputs=outputs, expression=expression, requirements=reqs, cwlVersion="v1.0", ) def traverse_step( step: cwl.WorkflowStep, parent: cwl.Workflow, replace_etool: bool, skip_command_line1: bool, skip_command_line2: bool, ) -> bool: """Process the given WorkflowStep.""" modified = False inputs = empty_inputs(step, parent) if not step.id: return False step_id = step.id.split("#")[-1] original_process = copy.deepcopy(step.run) original_step_ins = copy.deepcopy(step.in_) for inp in step.in_: if inp.valueFrom: if not inp.source: self = None else: if isinstance(inp.source, MutableSequence): self = [] for source in inp.source: if not step.scatter: self.append( example_input( utils.type_for_source(parent, source.split("#")[-1]) ) ) else: scattered_source_type = utils.type_for_source( parent, source ) if isinstance(scattered_source_type, list): for stype in scattered_source_type: self.append(example_input(stype.type_)) else: self.append(example_input(scattered_source_type.type_)) else: if not step.scatter: self = example_input( utils.type_for_source(parent, inp.source.split("#")[-1]) ) else: scattered_source_type2 = utils.type_for_source( parent, inp.source ) if isinstance(scattered_source_type2, list): self = example_input(scattered_source_type2[0].type_) else: self = example_input(scattered_source_type2.type_) expression = get_expression(inp.valueFrom, inputs, self) if expression: modified = True etool_id = "_expression_{}_{}".format(step_id, inp.id.split("/")[-1]) target = get_input_for_id(inp.id, original_process) if not target: raise WorkflowException("target not found") input_source_id = None source_type: None | ( MutableSequence[ cwl.CommandInputParameter | cwl.CommandOutputParameter | cwl.WorkflowInputParameter ] | cwl.CommandInputParameter | cwl.CommandOutputParameter | cwl.WorkflowInputParameter ) = None if inp.source: if isinstance(inp.source, MutableSequence): input_source_id = [] source_types: list[cwl.WorkflowInputParameter] = [] for source in inp.source: source_id = source.split("#")[-1] input_source_id.append(source_id) temp_type = utils.type_for_source( step.run, source_id, parent ) if isinstance(temp_type, list): for ttype in temp_type: if ttype not in source_types: source_types.append(ttype) else: if temp_type not in source_types: source_types.append(temp_type) source_type = cwl.WorkflowInputParameter( id=None, type_=cwl.ArraySchema(source_types, "array"), ) else: input_source_id = inp.source.split("#")[-1] source_type = utils.param_for_source_id( step.run, input_source_id, parent ) # target.id = target.id.split('#')[-1] if isinstance(original_process, cwl.ExpressionTool): found_JSReq = False reqs: list[cwl.ProcessRequirement] = [] if original_process.hints: reqs.extend(original_process.hints) if original_process.requirements: reqs.extend(original_process.requirements) for req in reqs: if isinstance(req, cwl.InlineJavascriptRequirement): found_JSReq = True if not found_JSReq: if not step.run.requirements: step.run.requirements = [] expr_lib = find_expressionLib([parent]) step.run.requirements.append( cwl.InlineJavascriptRequirement(expr_lib) ) replace_step_valueFrom_expr_with_etool( expression, etool_id, parent, target, step, inp, original_process, original_step_ins, input_source_id, replace_etool, source_type, ) inp.valueFrom = None inp.source = f"{etool_id}/result" if step.when: expression = get_expression(string=step.when, inputs=inputs, self=None) if expression: modified = True replace_step_when_expr_with_etool( expression, parent, step, original_step_ins, replace_etool ) # TODO: skip or special process for sub workflows? process_modified = process_level_reqs( original_process, step, parent, replace_etool, skip_command_line1, skip_command_line2, ) if process_modified: modified = True if isinstance(original_process, cwl.CommandLineTool): clt_modified = traverse_CommandLineTool( original_process, parent, step, replace_etool, skip_command_line1, skip_command_line2, ) if clt_modified: modified = True return modified def workflow_step_to_WorkflowInputParameters( step_ins: list[cwl.WorkflowStepInput], parent: cwl.Workflow, except_in_id: str ) -> MutableSequence[ cwl.CommandInputParameter | cwl.CommandOutputParameter | cwl.WorkflowInputParameter ]: """Create WorkflowInputParameters to match the given WorkflowStep inputs.""" params = [] for inp in step_ins: if not inp.id: continue inp_id = inp.id.split("#")[-1].split("/")[-1] if inp.source and inp_id != except_in_id: param = copy.deepcopy( utils.param_for_source_id(parent, sourcenames=inp.source) ) if isinstance(param, MutableSequence): for p in param: p.id = inp_id p.type_ = clean_type_ids(p.type_) params.append(p) else: param.id = inp_id param.type_ = clean_type_ids(param.type_) params.append(param) return params def replace_step_valueFrom_expr_with_etool( expr: str, name: str, workflow: cwl.Workflow, target: cwl.CommandInputParameter | cwl.WorkflowInputParameter, step: cwl.WorkflowStep, step_inp: cwl.WorkflowStepInput, original_process: cwl.CommandLineTool | cwl.ExpressionTool, original_step_ins: list[cwl.WorkflowStepInput], source: str | list[str] | None, replace_etool: bool, source_type: None | ( cwl.CommandInputParameter | cwl.CommandOutputParameter | cwl.WorkflowInputParameter | MutableSequence[ cwl.CommandInputParameter | cwl.CommandOutputParameter | cwl.WorkflowInputParameter ] ) = None, ) -> None: """Replace a WorkflowStep level 'valueFrom' expression with a sibling ExpressionTool step.""" if not step_inp.id: raise WorkflowException(f"Missing id in {step_inp}.") step_inp_id = step_inp.id.split("/")[-1] etool_inputs = workflow_step_to_WorkflowInputParameters( original_step_ins, workflow, step_inp_id ) if source: source_param = cwl.WorkflowInputParameter(id="self", type_="Any") # TODO: would be nicer to derive a proper type; but in the face of linkMerge, this is easier for now etool_inputs.append(source_param) temp_etool = generate_etool_from_expr2( expr, target, etool_inputs, "self" if source else None, original_process, [workflow, step], ) if replace_etool: processes: list[ (cwl.Workflow | cwl.CommandLineTool | cwl.ExpressionTool | cwl.WorkflowStep) ] = [ workflow, step, ] cltool = etool_to_cltool(temp_etool, find_expressionLib(processes)) etool: cwl.ExpressionTool | cwl.CommandLineTool = cltool else: etool = temp_etool wf_step_inputs = copy.deepcopy(original_step_ins) if source: wf_step_inputs.append(cwl.WorkflowStepInput(id="self", source=step_inp.source)) for wf_step_input in wf_step_inputs: if not wf_step_input.id: continue wf_step_input.id = wf_step_input.id.split("/")[-1] if wf_step_input.valueFrom: wf_step_input.valueFrom = None if wf_step_input.source: if isinstance(wf_step_input.source, MutableSequence): for index, inp_source in enumerate(wf_step_input.source): wf_step_input.source[index] = inp_source.split("#")[-1] else: wf_step_input.source = wf_step_input.source.split("#")[-1] wf_step_inputs[:] = [ x for x in wf_step_inputs if x.id and not (x.id.startswith("_") or x.id.endswith(step_inp_id)) ] scatter = copy.deepcopy(step.scatter) if isinstance(scatter, str): scatter = [scatter] if isinstance(scatter, MutableSequence): for index, entry in enumerate(scatter): scatter[index] = entry.split("/")[-1] if scatter and step_inp_id in scatter: scatter = ["self"] # do we still need to scatter? else: scatter = None workflow.steps.append( cwl.WorkflowStep( id=name, in_=wf_step_inputs, out=[cwl.WorkflowStepOutput("result")], run=etool, scatter=scatter, scatterMethod=step.scatterMethod, ) ) def replace_step_when_expr_with_etool( expr: str, workflow: cwl.Workflow, step: cwl.WorkflowStep, original_step_ins: list[cwl.WorkflowStepInput], replace_etool: bool, ) -> None: """Replace a WorkflowStep level 'when' expression with a sibling ExpressionTool step.""" if not step.id: raise WorkflowException(f"Missing id from {step}.") etool_id = "_when_expression_{}".format(step.id.split("#")[-1]) etool_inputs = workflow_step_to_WorkflowInputParameters( original_step_ins, workflow, "" ) temp_etool = generate_etool_from_expr2( expr, cwl.WorkflowInputParameter(id=None, type_="boolean"), etool_inputs, None, None, [workflow, step], ) if replace_etool: processes: list[ (cwl.Workflow | cwl.CommandLineTool | cwl.ExpressionTool | cwl.WorkflowStep) ] = [ workflow, step, ] cltool = etool_to_cltool(temp_etool, find_expressionLib(processes)) etool: cwl.ExpressionTool | cwl.CommandLineTool = cltool else: etool = temp_etool wf_step_inputs = copy.deepcopy(original_step_ins) for wf_step_input in wf_step_inputs: if not wf_step_input.id: continue wf_step_input.id = wf_step_input.id.split("/")[-1] if wf_step_input.source: if isinstance(wf_step_input.source, MutableSequence): for index, inp_source in enumerate(wf_step_input.source): wf_step_input.source[index] = inp_source.split("#")[-1] else: wf_step_input.source = wf_step_input.source.split("#")[-1] wf_step_inputs[:] = [x for x in wf_step_inputs if x.id and not x.id.startswith("_")] scatter = copy.deepcopy(step.scatter) if isinstance(scatter, str): scatter = [scatter] if isinstance(scatter, MutableSequence): for index, entry in enumerate(scatter): scatter[index] = entry.split("/")[-1] scatter = step.scatter workflow.steps.append( cwl.WorkflowStep( id=etool_id, in_=wf_step_inputs, out=[cwl.WorkflowStepOutput("result")], run=etool, scatter=scatter, scatterMethod=step.scatterMethod, ) ) step.when = "$(inputs._when)" step.in_.append(cwl.WorkflowStepInput(id="_when", source=f"{etool_id}/result")) def traverse_workflow( workflow: cwl.Workflow, replace_etool: bool, skip_command_line1: bool, skip_command_line2: bool, ) -> tuple[cwl.Workflow, bool]: """Traverse a workflow, processing each step.""" modified = False for index, step in enumerate(workflow.steps): if isinstance(step.run, cwl.ExpressionTool) and replace_etool: workflow.steps[index].run = etool_to_cltool(step.run) modified = True else: step_modified = load_step( step, replace_etool, skip_command_line1, skip_command_line2 ) if step_modified: modified = True for step in workflow.steps: if not step.id.startswith("_expression"): step_modified = traverse_step( step, workflow, replace_etool, skip_command_line1, skip_command_line2 ) if step_modified: modified = True if process_workflow_inputs_and_outputs(workflow, replace_etool): modified = True if process_workflow_reqs_and_hints(workflow, replace_etool): modified = True if workflow.requirements: workflow.requirements[:] = [ x for x in workflow.requirements if not isinstance( x, (cwl.InlineJavascriptRequirement, cwl.StepInputExpressionRequirement) ) ] else: workflow.requirements = None return workflow, modified cwl_utils-0.41/cwl_utils/docker_extract.py0000755000000000000000000001120313615410400015743 0ustar00#!/usr/bin/env python3 # SPDX-License-Identifier: Apache-2.0 import argparse import sys from collections.abc import Iterator from pathlib import Path from typing import cast import ruamel.yaml import cwl_utils.parser as cwl from cwl_utils.image_puller import ( DockerImagePuller, ImagePuller, SingularityImagePuller, ) def arg_parser() -> argparse.ArgumentParser: """Argument parser.""" parser = argparse.ArgumentParser( description="Save container images specified in a CWL document (Workflow or CommandLineTool). " "For CWL Workflows, all steps will also be searched (recursively)." ) parser.add_argument( "input", help="Input CWL document (CWL Workflow or CWL CommandLineTool)" ) parser.add_argument("--dir", help="Directory in which to save images") parser.add_argument( "-s", "--singularity", help="Use singularity to pull the image", action="store_true", ) parser.add_argument( "--container-engine", dest="container_engine", help="Specify which command to use to run OCI containers. " "Defaults to 'docker' (or 'singularity' if --singularity/-s is passed).", ) parser.add_argument( "--force-download", help="Force pulling a newer container.", action="store_true" ) return parser def run(args: argparse.Namespace) -> list[cwl.DockerRequirement]: """Extract the docker reqs and download them using Singularity or Docker.""" if args.singularity and not args.dir: print("Error! Must specify --dir if using --singularity") sys.exit(1) if args.dir: Path(args.dir).mkdir(parents=True, exist_ok=True) top = cwl.load_document_by_uri(args.input) reqs: list[cwl.DockerRequirement] = [] for req in traverse(top): reqs.append(req) if not req.dockerPull: print( "Unable to save image from due to lack of 'dockerPull':", file=sys.stderr, ) yaml = ruamel.yaml.YAML() yaml.dump(req.save(), sys.stderr) continue if args.singularity: image_puller: ImagePuller = SingularityImagePuller( req.dockerPull, args.dir, ( args.container_engine if args.container_engine is not None else "singularity" ), args.force_download, ) else: image_puller = DockerImagePuller( req.dockerPull, args.dir, ( args.container_engine if args.container_engine is not None else "docker" ), args.force_download, ) image_puller.save_docker_image() return reqs def extract_docker_requirements( process: cwl.Process, ) -> Iterator[cwl.DockerRequirement]: """Yield an iterator of the docker reqs, normalizing the pull request.""" for req in extract_docker_reqs(process): if isinstance(req.dockerPull, str) and ":" not in req.dockerPull: req.dockerPull += ":latest" yield req def extract_docker_reqs(process: cwl.Process) -> Iterator[cwl.DockerRequirement]: """For the given process, extract the DockerRequirement(s).""" if process.requirements: for req in process.requirements: if isinstance(req, cwl.DockerRequirementTypes): yield req if process.hints: for req in process.hints: if isinstance(req, cwl.DockerRequirementTypes): yield req def traverse(process: cwl.Process) -> Iterator[cwl.DockerRequirement]: """Yield the iterator for the docker reqs, including an workflow steps.""" yield from extract_docker_requirements(process) if isinstance(process, cwl.WorkflowTypes): yield from traverse_workflow(process) def get_process_from_step(step: cwl.WorkflowStep) -> cwl.Process: """Return the process for this step, loading it if necessary.""" if isinstance(step.run, str): return cast(cwl.Process, cwl.load_document_by_uri(step.run)) return cast(cwl.Process, step.run) def traverse_workflow(workflow: cwl.Workflow) -> Iterator[cwl.DockerRequirement]: """Iterate over the steps of this workflow, yielding the docker reqs.""" for step in workflow.steps: yield from extract_docker_reqs(step) yield from traverse(get_process_from_step(step)) def main() -> int: """Command line entry point.""" run(arg_parser().parse_args(sys.argv[1:])) return 0 if __name__ == "__main__": sys.exit(main()) cwl_utils-0.41/cwl_utils/errors.py0000644000000000000000000000166113615410400014262 0ustar00# SPDX-License-Identifier: Apache-2.0 """Common Exceptions.""" class ArrayMissingItems(BaseException): """From https://github.com/rabix/sbpack/blob/b8404a0859ffcbe1edae6d8f934e51847b003320/sbpack/lib.py .""" class JavascriptException(Exception): pass class MissingKeyField(BaseException): """From https://github.com/rabix/sbpack/blob/b8404a0859ffcbe1edae6d8f934e51847b003320/sbpack/lib.py .""" class MissingTypeName(BaseException): """From https://github.com/rabix/sbpack/blob/b8404a0859ffcbe1edae6d8f934e51847b003320/sbpack/lib.py .""" class RecordMissingFields(BaseException): """From https://github.com/rabix/sbpack/blob/b8404a0859ffcbe1edae6d8f934e51847b003320/sbpack/lib.py .""" class SubstitutionError(Exception): pass class WorkflowException(Exception): pass class GraphTargetMissingException(WorkflowException): """When a $graph is encountered and there is no target and no main/#main.""" cwl_utils-0.41/cwl_utils/expression.py0000644000000000000000000002544313615410400015151 0ustar00# SPDX-License-Identifier: Apache-2.0 """CWL Expression parsing.""" import asyncio import inspect import json from collections.abc import Awaitable, Container from enum import Enum from typing import Any, Final, cast from schema_salad.utils import json_dumps from cwl_utils.errors import JavascriptException, SubstitutionError, WorkflowException from cwl_utils.loghandler import _logger from cwl_utils.sandboxjs import JSEngine, default_timeout, get_js_engine, param_re from cwl_utils.types import ( CWLObjectType, CWLOutputType, CWLParameterContext, is_cwl_parameter_context_key, ) from cwl_utils.utils import bytes2str_in_dicts OLD_ESCAPE_CWL_VERSIONS: Final[Container[str]] = ( "v1.0", "v1.1.0-dev1", "v1.1", "v1.2.0-dev1", "v1.2.0-dev2", "v1.2.0-dev3", ) def _convert_dumper(string: str) -> str: return f"{json.dumps(string)} + " class t(Enum): """Tokens.""" DEFAULT = 0 DOLLAR = 1 PAREN = 2 BRACE = 3 SINGLE_QUOTE = 4 DOUBLE_QUOTE = 5 BACKSLASH = 6 def scanner(scan: str) -> tuple[int, int] | None: """Find JS relevant punctuation in a string.""" i = 0 stack: list[t] = [t.DEFAULT] start = 0 while i < len(scan): c = scan[i] state = stack[-1] match state: case t.DEFAULT: if c == "$": stack.append(t.DOLLAR) elif c == "\\": stack.append(t.BACKSLASH) case t.BACKSLASH: stack.pop() if stack[-1] == t.DEFAULT: return i - 1, i + 1 case t.DOLLAR: if c == "(": start = i - 1 stack.append(t.PAREN) elif c == "{": start = i - 1 stack.append(t.BRACE) else: stack.pop() i -= 1 case t.PAREN: if c == "(": stack.append(t.PAREN) elif c == ")": stack.pop() if stack[-1] == t.DOLLAR: return start, i + 1 elif c == "'": stack.append(t.SINGLE_QUOTE) elif c == '"': stack.append(t.DOUBLE_QUOTE) case t.BRACE: if c == "{": stack.append(t.BRACE) elif c == "}": stack.pop() if stack[-1] == t.DOLLAR: return start, i + 1 elif c == "'": stack.append(t.SINGLE_QUOTE) elif c == '"': stack.append(t.DOUBLE_QUOTE) case t.SINGLE_QUOTE: if c == "'": stack.pop() elif c == "\\": stack.append(t.BACKSLASH) case t.DOUBLE_QUOTE: if c == '"': stack.pop() elif c == "\\": stack.append(t.BACKSLASH) i += 1 if len(stack) > 1 and not (len(stack) == 2 and stack[1] in (t.BACKSLASH, t.DOLLAR)): raise SubstitutionError( "Substitution error, unfinished block starting at position {}: '{}' stack was {}".format( start, scan[start:], stack ) ) return None def evaluator( js_engine: JSEngine, ex: str, obj: CWLParameterContext, jslib: str, fullJS: bool, **kwargs: Any, ) -> CWLOutputType | None: js_engine = js_engine or get_js_engine() expression_parse_exception = None if (match := param_re.match(ex)) is not None: first_symbol = match.group(1) first_symbol_end = match.end(1) if first_symbol_end + 1 == len(ex) and first_symbol == "null": return None try: if is_cwl_parameter_context_key(first_symbol): if inspect.iscoroutinefunction(js_engine.regex_eval): return asyncio.get_event_loop().run_until_complete( cast( Awaitable[CWLOutputType], js_engine.regex_eval( first_symbol, ex[first_symbol_end:-1], cast(CWLOutputType, obj[first_symbol]), **kwargs, ), ) ) else: return cast( CWLOutputType, js_engine.regex_eval( first_symbol, ex[first_symbol_end:-1], cast(CWLOutputType, obj[first_symbol]), **kwargs, ), ) else: raise WorkflowException(f"{first_symbol} is unexpected.") except WorkflowException as werr: expression_parse_exception = werr if fullJS: if inspect.iscoroutinefunction(js_engine.eval): return asyncio.get_event_loop().run_until_complete( cast(Awaitable[CWLOutputType], js_engine.eval(ex, jslib, **kwargs)) ) else: return cast(CWLOutputType, js_engine.eval(ex, jslib, **kwargs)) else: if expression_parse_exception is not None: raise JavascriptException( "Syntax error in parameter reference '%s': %s. This could be " "due to using Javascript code without specifying " "InlineJavascriptRequirement." % (ex[1:-1], expression_parse_exception) ) else: raise JavascriptException( "Syntax error in parameter reference '%s'. This could be due " "to using Javascript code without specifying " "InlineJavascriptRequirement." % ex ) def interpolate( scan: str, rootvars: CWLParameterContext, jslib: str = "", fullJS: bool = False, strip_whitespace: bool = True, escaping_behavior: int = 2, convert_to_expression: bool = False, js_engine: JSEngine | None = None, **kwargs: Any, ) -> CWLOutputType | None: """ Interpolate and evaluate. Note: only call with convert_to_expression=True on CWL Expressions in $() form that need interpolation. """ if strip_whitespace: scan = scan.strip() parts = [] if convert_to_expression: dump = _convert_dumper parts.append("${return ") else: def dump(string: str) -> str: return string w = scanner(scan) while w: if convert_to_expression: parts.append(f'"{scan[0: w[0]]}" + ') # noqa: B907 else: parts.append(scan[0 : w[0]]) if scan[w[0]] == "$": if not convert_to_expression: js_engine = js_engine or get_js_engine() e = evaluator( js_engine, scan[w[0] + 1 : w[1]], rootvars, jslib, fullJS, **kwargs ) if w[0] == 0 and w[1] == len(scan) and len(parts) <= 1: return e leaf = json_dumps(e, sort_keys=True) if leaf[0] == '"': leaf = json.loads(leaf) parts.append(leaf) else: parts.append( "function(){var item =" + scan[w[0] : w[1]][2:-1] + '; if (typeof(item) === "string"){ return item; } ' "else { return JSON.stringify(item); }}() + " ) elif scan[w[0]] == "\\": if escaping_behavior == 1: # Old behavior. Just skip the next character. e = scan[w[1] - 1] parts.append(dump(e)) elif escaping_behavior == 2: # Backslash quoting requires a three character lookahead. e = scan[w[0] : w[1] + 1] if e in ("\\$(", "\\${"): # Suppress start of a parameter reference, drop the # backslash. parts.append(dump(e[1:])) w = (w[0], w[1] + 1) elif e[1] == "\\": # Double backslash, becomes a single backslash parts.append(dump("\\")) else: # Some other text, add it as-is (including the # backslash) and resume scanning. parts.append(dump(e[:2])) else: raise Exception("Unknown escaping behavior %s" % escaping_behavior) scan = scan[w[1] :] w = scanner(scan) if convert_to_expression: parts.extend((f'"{scan}"', ";}")) # noqa: B907 else: parts.append(scan) return "".join(parts) def jshead(engine_config: list[str], rootvars: CWLParameterContext) -> str: """Make sure all the byte strings are converted to str in `rootvars` dict.""" return "\n".join( engine_config + [f"var {k} = {json_dumps(v, indent=4)};" for k, v in rootvars.items()] ) def needs_parsing(snippet: Any) -> bool: return isinstance(snippet, str) and ("$(" in snippet or "${" in snippet) def do_eval( ex: CWLOutputType | None, jobinput: CWLObjectType, requirements: list[CWLObjectType], outdir: str | None, tmpdir: str | None, resources: dict[str, float | int], context: CWLOutputType | None = None, timeout: float = default_timeout, strip_whitespace: bool = True, cwlVersion: str = "", **kwargs: Any, ) -> CWLOutputType | None: """ Evaluate the given CWL expression, in context. :param timeout: The maximum number of seconds to wait while executing. """ runtime = resources | {"tmpdir": tmpdir or None, "outdir": outdir or None} rootvars = cast( CWLParameterContext, bytes2str_in_dicts({"inputs": jobinput, "self": context, "runtime": runtime}), ) if isinstance(ex, str) and needs_parsing(ex): fullJS = False jslib = "" for r in reversed(requirements): if r["class"] == "InlineJavascriptRequirement": fullJS = True jslib = jshead(cast(list[str], r.get("expressionLib", [])), rootvars) break try: return interpolate( ex, rootvars, timeout=timeout, fullJS=fullJS, jslib=jslib, strip_whitespace=strip_whitespace, escaping_behavior=1 if cwlVersion in OLD_ESCAPE_CWL_VERSIONS else 2, **kwargs, ) except Exception as e: _logger.exception(e) raise WorkflowException("Expression evaluation error:\n%s" % str(e)) from e else: return ex cwl_utils-0.41/cwl_utils/expression_refactor.py0000755000000000000000000001333513615410400017036 0ustar00#!/usr/bin/env python3 # SPDX-License-Identifier: Apache-2.0 # Copyright 2018-2021 Michael R. Crusoe """CWL Expression refactoring tool for CWL.""" import argparse import logging import shutil import sys from collections.abc import Callable, MutableMapping, MutableSequence from pathlib import Path from typing import Any, Protocol from ruamel.yaml.main import YAML from ruamel.yaml.scalarstring import walk_tree from cwl_utils import ( cwl_v1_0_expression_refactor, cwl_v1_1_expression_refactor, cwl_v1_2_expression_refactor, ) from cwl_utils.errors import WorkflowException from cwl_utils.loghandler import _logger as _cwlutilslogger from cwl_utils.parser import cwl_v1_0, cwl_v1_1, cwl_v1_2 _logger = logging.getLogger("cwl-expression-refactor") # pylint: disable=invalid-name defaultStreamHandler = logging.StreamHandler() # pylint: disable=invalid-name _logger.addHandler(defaultStreamHandler) _logger.setLevel(logging.INFO) _cwlutilslogger.setLevel(100) save_type = ( MutableMapping[str, Any] | MutableSequence[Any] | int | float | bool | str | None ) class saveCWL(Protocol): """Shortcut type for CWL v1.x parse.save().""" def __call__( self, val: Any, top: bool = True, base_url: str = "", relative_uris: bool = True, ) -> save_type: """Must use this instead of a Callable due to the keyword args.""" ... def arg_parser() -> argparse.ArgumentParser: """Build the argument parser.""" parser = argparse.ArgumentParser( description="Tool to refactor CWL documents so that any CWL expression " "are separate steps as either ExpressionTools or CommandLineTools. Exit code 7 " "means a single CWL document was provided but it did not need modification." ) parser.add_argument( "--etools", help="Output ExpressionTools, don't go all the way to CommandLineTools.", action="store_true", ) parser.add_argument( "--skip-some1", help="Don't process CommandLineTool.inputs.inputBinding and CommandLineTool.arguments sections.", action="store_true", ) parser.add_argument( "--skip-some2", help="Don't process CommandLineTool.outputEval or " "CommandLineTool.requirements.InitialWorkDirRequirement.", action="store_true", ) parser.add_argument("dir", help="Directory in which to save converted files") parser.add_argument( "inputs", nargs="+", help="One or more CWL documents.", ) return parser def parse_args(args: list[str]) -> argparse.Namespace: """Parse the command line options.""" return arg_parser().parse_args(args) def main() -> None: """Console entry point.""" sys.exit(run(sys.argv[1:])) def run(args: list[str]) -> int: """Collect the arguments and run.""" return refactor(parse_args(args)) def refactor(args: argparse.Namespace) -> int: """Primary processing loop.""" return_code = 0 yaml = YAML(typ="rt") yaml.preserve_quotes = True for document in args.inputs: _logger.info("Processing %s.", document) with open(document) as doc_handle: result = yaml.load(doc_handle) uri = Path(document).resolve().as_uri() match result["cwlVersion"]: case "v1.0": top = cwl_v1_0.load_document_by_yaml(result, uri) traverse: Callable[[Any, bool, bool, bool, bool], tuple[Any, bool]] = ( cwl_v1_0_expression_refactor.traverse ) save: saveCWL = cwl_v1_0.save case "v1.1": top = cwl_v1_1.load_document_by_yaml(result, uri) traverse = cwl_v1_1_expression_refactor.traverse save = cwl_v1_1.save case "v1.2": top = cwl_v1_2.load_document_by_yaml(result, uri) traverse = cwl_v1_2_expression_refactor.traverse save = cwl_v1_2.save case _: _logger.error( "Sorry, %s is not a supported CWL version by this tool.", result["cwlVersion"], ) return -1 try: result, modified = traverse( top, not args.etools, False, args.skip_some1, args.skip_some2 ) output = Path(args.dir) / Path(document).name if not modified: if len(args.inputs) > 1: shutil.copyfile(document, output) continue else: return 7 if not isinstance(result, MutableSequence): result_json = save( result, base_url=(result.loadingOptions.fileuri or ""), ) # ^^ Setting the base_url and keeping the default value # for relative_uris=True means that the IDs in the generated # JSON/YAML are kept clean of the path to the input document else: result_json = [ save(result_item, base_url=result_item.loadingOptions.fileuri) for result_item in result ] walk_tree(result_json) # ^ converts multiline strings to nice multiline YAML with output.open("w", encoding="utf-8") as output_filehandle: output_filehandle.write( "#!/usr/bin/env cwl-runner\n" ) # TODO: teach the codegen to do this? yaml.dump(result_json, output_filehandle) except WorkflowException as exc: return_code = 1 _logger.exception("Skipping %s due to error.", document, exc_info=exc) return return_code if __name__ == "__main__": main() cwl_utils-0.41/cwl_utils/file_formats.py0000644000000000000000000000420313615410400015413 0ustar00# SPDX-License-Identifier: Apache-2.0 """ CWL file formats utilities. For more information, please visit https://www.commonwl.org/user_guide/16-file-formats/ """ from rdflib import OWL, RDFS, Graph, URIRef from schema_salad.exceptions import ValidationException from schema_salad.utils import aslist, json_dumps from cwl_utils.types import CWLFileType def formatSubclassOf( fmt: str, cls: str, ontology: Graph | None, visited: set[str] ) -> bool: """Determine if `fmt` is a subclass of `cls`.""" if URIRef(fmt) == URIRef(cls): return True if ontology is None: return False if fmt in visited: return False visited.add(fmt) uriRefFmt = URIRef(fmt) for _s, _p, o in ontology.triples((uriRefFmt, RDFS.subClassOf, None)): # Find parent classes of `fmt` and search upward if formatSubclassOf(o, cls, ontology, visited): return True for _s, _p, o in ontology.triples((uriRefFmt, OWL.equivalentClass, None)): # Find equivalent classes of `fmt` and search horizontally if formatSubclassOf(o, cls, ontology, visited): return True for s, _p, _o in ontology.triples((None, OWL.equivalentClass, uriRefFmt)): # Find equivalent classes of `fmt` and search horizontally if formatSubclassOf(s, cls, ontology, visited): return True return False def check_format( actual_file: CWLFileType | list[CWLFileType], input_formats: list[str] | str, ontology: Graph | None, ) -> None: """Confirm that the format present is valid for the allowed formats.""" for afile in aslist(actual_file): if not afile: continue if "format" not in afile: raise ValidationException( f"File has no 'format' defined: {json_dumps(afile, indent=4)}" ) for inpf in aslist(input_formats): if afile["format"] == inpf or formatSubclassOf( afile["format"], inpf, ontology, set() ): return raise ValidationException( f"File has an incompatible format: {json_dumps(afile, indent=4)}" ) cwl_utils-0.41/cwl_utils/graph_split.py0000755000000000000000000002502313615410400015263 0ustar00#!/usr/bin/env python # SPDX-License-Identifier: Apache-2.0 # Copyright 2019-2020 Michael R. Crusoe # Copyright 2020 Altair Wei """ Unpacks the result of `cwltool --unpack`. Only tested with a single v1.0 workflow. """ import argparse import json import logging import os import re import sys from collections.abc import MutableMapping from io import TextIOWrapper from pathlib import Path from typing import ( IO, Any, Callable, cast, ) try: stringify_dict: Callable[[dict[str, Any]], str] | None from cwlformat.formatter import stringify_dict except ImportError: stringify_dict = None from ruamel.yaml.main import YAML from ruamel.yaml.representer import RoundTripRepresenter from schema_salad.sourceline import SourceLine, add_lc_filename from cwl_utils.loghandler import _logger as _cwlutilslogger _logger = logging.getLogger("cwl-graph-split") # pylint: disable=invalid-name defaultStreamHandler = logging.StreamHandler() # pylint: disable=invalid-name _logger.addHandler(defaultStreamHandler) _logger.setLevel(logging.INFO) _cwlutilslogger.setLevel(100) def arg_parser() -> argparse.ArgumentParser: """Build the argument parser.""" parser = argparse.ArgumentParser(description="Split a packed CWL document.") parser.add_argument("cwlfile") parser.add_argument( "-m", "--mainfile", default=None, type=str, help="Specify the name of the main document.", ) parser.add_argument( "-f", "--output-format", choices=["json", "yaml"], type=str, default="json", help="Specify the format of the output CWL files.", ) parser.add_argument( "-p", "--pretty", action="store_true", default=False, help="Beautify the output CWL document, only works with yaml format.", ) parser.add_argument( "-C", "--outdir", type=str, default=Path.cwd(), help="Output folder for the unpacked CWL files.", ) return parser def main() -> None: """Console entry point.""" sys.exit(run(sys.argv[1:])) def run(args: list[str]) -> int: """Split the packed CWL at the path of the first argument.""" options = arg_parser().parse_args(args) with open(options.cwlfile) as source_handle: graph_split( source_handle, Path(options.outdir), options.output_format, options.mainfile, options.pretty, ) return 0 def graph_split( sourceIO: IO[str], output_dir: Path, output_format: str, mainfile: str, pretty: bool, ) -> None: """Loop over the provided packed CWL document and split it up.""" yaml = YAML(typ="rt") yaml.preserve_quotes = True source = yaml.load(sourceIO) add_lc_filename(source, sourceIO.name) if "$graph" not in source: print("No $graph, so not for us.") return version = source.pop("cwlVersion") # Check outdir parent exists if not output_dir.parent.is_dir(): raise NotADirectoryError(f"Parent directory of {output_dir} does not exist") # If output_dir is not a directory, create it if not output_dir.is_dir(): output_dir.mkdir() def my_represent_none( self: Any, data: Any ) -> Any: # pylint: disable=unused-argument """Force clean representation of 'null'.""" return self.represent_scalar("tag:yaml.org,2002:null", "null") RoundTripRepresenter.add_representer(type(None), my_represent_none) for entry in source["$graph"]: entry_id = entry.pop("id").lstrip("#") entry["cwlVersion"] = version imports = rewrite(entry, entry_id, output_dir) if imports: for import_name in imports: rewrite_types(entry, f"#{import_name}", False) if entry_id == "main": if mainfile is None: entry_id = f"unpacked_{os.path.basename(sourceIO.name)}" else: entry_id = mainfile output_file = output_dir / (re.sub(".cwl$", "", entry_id) + ".cwl") if output_format == "json": json_dump(entry, output_file) elif output_format == "yaml": with output_file.open("w", encoding="utf-8") as output_handle: yaml_dump(entry, output_handle, pretty) def rewrite_id(entry: Any, this_id: str | None) -> MutableMapping[Any, Any] | str: if isinstance(entry, MutableMapping): if entry["id"].startswith(this_id): assert isinstance(this_id, str) # nosec B101 entry["id"] = cast(str, entry["id"])[len(this_id) + 1 :] return entry elif isinstance(entry, str): if this_id and entry.startswith(this_id): return entry[len(this_id) + 1 :] return entry raise Exception(f"{entry} is neither a dictionary nor string.") def rewrite( document: Any, doc_id: str, output_dir: Path, pretty: bool = False ) -> set[str]: """Rewrite the given element from the CWL $graph.""" imports = set() if isinstance(document, list) and not isinstance(document, str): for entry in document: imports.update(rewrite(entry, doc_id, output_dir, pretty)) elif isinstance(document, dict): this_id = document["id"] if "id" in document else None for key, value in document.items(): with SourceLine(document, key, Exception): match key: case "run" if isinstance(value, str) and value[0] == "#": document[key] = f"{re.sub('.cwl$', '', value[1:])}.cwl" case "id" | "outputSource" if value.startswith("#" + doc_id): document[key] = value[len(doc_id) + 2 :] case "out" if isinstance(value, list): document[key][:] = [ rewrite_id(entry, this_id) for entry in value ] case "source" | "scatter" | "items" | "format": if ( isinstance(value, str) and value.startswith("#") and "/" in value ): referrant_file, sub = value[1:].split("/", 1) if referrant_file == doc_id: document[key] = sub else: document[key] = f"{referrant_file}#{sub}" elif isinstance(value, list): new_sources = [] for entry in value: if entry.startswith("#" + doc_id): new_sources.append(entry[len(doc_id) + 2 :]) else: new_sources.append(entry) document[key] = new_sources case "$import": rewrite_import(document) case "class" if value == "SchemaDefRequirement": return rewrite_schemadef(document, output_dir, pretty) case _: imports.update(rewrite(value, doc_id, output_dir, pretty)) return imports def rewrite_import(document: MutableMapping[str, Any]) -> None: """Adjust the $import directive.""" external_file = document["$import"].split("/")[0].lstrip("#") document["$import"] = external_file def rewrite_types(field: Any, entry_file: str, sameself: bool) -> None: """Clean up the names of the types.""" if isinstance(field, list) and not isinstance(field, str): for entry in field: rewrite_types(entry, entry_file, sameself) return if isinstance(field, dict): for key, value in field.items(): for name in ("type", "items"): if key == name: if isinstance(value, str) and value.startswith(entry_file): if sameself: field[key] = value[len(entry_file) + 1 :] else: field[key] = "{d[0]}#{d[1]}".format( d=value[1:].split("/", 1) ) if isinstance(value, dict): rewrite_types(value, entry_file, sameself) if isinstance(value, list) and not isinstance(value, str): for entry in value: rewrite_types(entry, entry_file, sameself) def rewrite_schemadef( document: MutableMapping[str, Any], output_dir: Path, pretty: bool = False ) -> set[str]: """Dump the schemadefs to their own file.""" for entry in document["types"]: if "$import" in entry: rewrite_import(entry) elif "name" in entry and "/" in entry["name"]: entry_file, entry["name"] = entry["name"].lstrip("#").split("/") for field in entry.get("fields", []): field["name"] = field["name"].split("/")[2] rewrite_types(field, entry_file, True) with (output_dir / entry_file).open("a", encoding="utf-8") as entry_handle: yaml_dump(entry, entry_handle, pretty) entry["$import"] = entry_file del entry["name"] del entry["type"] if "fields" in entry: del entry["fields"] seen_imports = set() def seen_import(entry: MutableMapping[str, Any]) -> bool: if "$import" in entry: external_file = entry["$import"] if external_file not in seen_imports: seen_imports.add(external_file) return True return False return True types = document["types"] document["types"][:] = [entry for entry in types if seen_import(entry)] return seen_imports def json_dump(entry: Any, output_file: Path) -> None: """Output object as JSON.""" with output_file.open("w", encoding="utf-8") as result_handle: json.dump(entry, result_handle, indent=4) def yaml_dump( entry: Any, output_handle: TextIOWrapper, pretty: bool, ) -> None: """Output object as YAML.""" if pretty: if not stringify_dict: raise RuntimeError( "yaml_dump(pretty=True) requires cwlformat to be installed." ) output_handle.write(stringify_dict(entry)) return yaml = YAML(typ="rt", pure=True) yaml.default_flow_style = False yaml.indent = 4 yaml.block_seq_indent = 2 yaml.dump(entry, output_handle) if __name__ == "__main__": main() cwl_utils-0.41/cwl_utils/hello.simg0000755000000000000000000001003713615410400014360 0ustar00#!/usr/bin/env run-singularity hsqs%1[Àøw o ÿÿÿÿÿÿÿÿ°V ï a xÚíYÝnÛÈvÚíЋ}€½8•ƒM²È8mÚ­âµeG¨" ’Ò"h cHŽÄÙPufhE »ï°oÒ^õ!ú$y„ÞôœR¢)ɱ´)жLrÎùæœïüÌ ½û+?©¯ãZm,èP‰™‘‚ïi‘N²„)a^äóôÜÿÊÓñ7ÉàGŒáÏÐCý¶SªÃ_¾óÔŽÒÇ[ÙgcQ‹dÊk5þЇ8ö¸^ÛýÓ£ªáÚ@3E‰7ÃNïäY÷`Ð=?;è÷{OÛ­æ÷õ¬˜Ë)¼‚º¯C1öÙl¦ýmºNDei>{Å.çý pe"Ñ|…Æê= Ãc°Ôâ5”©a"åà„-ØêtÉFa`¯ ­Æ“ Tb³ÑÓÜË­¢Î™¥#ït"K£†Í J@ž6õÕ\ù‡‹FüÔ*“<|ÒîvëÐd–Á CUêÖEœg%¶ÚƒÁé ÇL$Y$+%ftÌ“˜†ˆmȃÜy±w§{¾|P+…ûbœ-}#b–¦YÍýåˆ}Öîí×Ëa»0×áiotÐéµ­/æ ØL*ãÐH¿E‚†f3•*,Ò¤j×6«r›ÊlI‘Jêåd"‘äRiˆmÓ¦¨!•ó†1Ïi+eÚ.%ÏœSbŽ_Ú0´ÄxýÎì‘K¤Gù£ÓÞ ÚOOÿØ®½º&QFÑøi»¡º­W­ï²ðG+ÂÿRƒ'÷ìíâ:mô‡hé—wôªk›ƒ]²þò>¾,7ãÍ›¹í9»€?‡r¶Pb¸Þƒ÷÷~×į¯0\tY ÐIC°œ¬”Å5Wç<ò6*7Êöþ «·Ýîá6€M›çDñ‰T xêÁ2e^sµÕŒM0¿ÍaF1‡Ÿðuä˜"ÏRqΕ&BñÉ!ÃJ• Ö@+™Mbè²¹âiÈá[®^ò„/ ÇŒ)Kp(вí®Î‚ïxh¨)rªI„dé¡ÿk&”Ë+%ÏY‚ù¦äÔ™à =8â3ã‘|#:YÜóàG±Ð åØÌ©%âu"Bžj„ÇÀ„`fÚÈ©x~Ý –i´~xT"z?áLS¯Ä<ÒYb Û9l÷†mÌã„C„ýY‰ 30&¶†j™©çÔá¬è‰uƒÃT„¡F´ÊV#4/ÖÕ Îi¶çþôNG89eŽÍíz{Î9[º6Æ?”Ýkìa‹œb`Ñ8t$"÷ÑJæDb S+C.c@ð2Áý§2ÒrE¹ñ˜_hfÆ.Ö1b4.à<…‰b)ÑDýCÍ“±W¢’ÒÀB[Œ2¥1„ xÌHfLDÍlÖÀe,å¯Â$Ó˜ˆ Jñs² Á›¹TI4/âFMžŒ)("Û(Û0Q¢F‰èPηA Y FcFTa€¹ç˜Åçœfy‰µF#ÜŒ+tdšË'ŽCD%l±|ØpÌJ’žb´¾Ò}$1´¸¨ÖèLbw ýƒÑ“ýºŸiå'è[âkì;­Òýòv5`/Ü-~Õ±ªmJ®iBI·+ %¤c™%„$‘óÚÅÖö?ÐÙ†œÛ0žöŸ:'OFÞ4r•ÆŒ0rÖL(בlì¶£u¶ *öË<33Ó-ߟ`yfÊ©_ZI(;Ê÷~ÈÀŸ2m¸òËV8ûláY{¨®iw•÷ÇòŠÓÅÝÕ«Òº“׿Cj¥þGšyÊRŠb–è"uó6³ôß®[ÅàuX@`äî=XXYâ®­ä5bât%Ÿ± S¬MÛrLÁQ¦X A^b¸èNe$Æö )™± 3t}¡ï‘¹XæØå±%„R9DÇ”ãgµ÷ØÌ”w“=Ø®]ó¨ a¡ãÚSÔ ïj +oí×+{¹èj±ênxØ9¦ñá~I½¾6<8=í_e‚òÌY^BXͶ”Ê;л[·I4?:2ì;Ø*±QQ?Œì"ŽÙm÷P´({L¼Ô¹.[Ôà*„]ËhÛ,sà ezÃpUÝ£³nçÛÁÁàùaÝØ„ÛäN~ÿªX­ÛÍúØ<¶nCS^RÊ>»“Ò•tغ¿×Ä%‡ã‘kýd•Ÿ®nŠWvèýŒüýýfÉãfë:ìÆ”¶ÛŽg‡¶EÑ{Ú·r®–Ræn9¢m= ‘!ŸN=ŸN=ŸN=ŸN=ÿ¹Sk˯q‹V]¸.4Úõõ°ò*×>]z ´&_…om ¦W}LïŒ7/œöÍñû÷ÅÿÃz-»Ü{Ÿ=¶gGíãN¯}tÖ´ûíÞ‘‹îP/Ä:Ø;Ôp÷ùÆþuA»t:\êÞ9[y©öU&»®O+Ø ãèÎÛ݆ùr}©—HÙÍDùeCíÍ÷¥—äù‹VzY ëÕ‘þÐîߺuk§øülçç;t÷ðñß?kì¬>¿Ù¥Žýí—o¿ð’~AÏ>ßÙyB3¸þUûG…~úçoÿõoÃW„¤xÚ…”;NÃ@†ÇvNx?yòJBG %Ô€è(S $bdd; „„è8 B¢¡á9âT…Y³Šg7‰¼Òʶ>ÿ³ÿü»Z º àÈ¿«UöÂfgųœ³¶]s-ÿ¦rbÔ¾Õr<ü6‘¨\’.qÛUh\‘®ðš¦m«ðÓÓŒ€8îpR>*1f‹rð/dçO¾Ç‘' ?F3{*ë!äqÎX‡8c’¿q¢E3õXÈ·2zu‚ð~HúIŸ"üyNù4áO)€R\ä3„wp+;¤?æoŒô÷ûBŒÏÒõ ÿÿÑ|æˆ^ƒ>ý<Ñ? ~Iê/Eø3ò$ˆþbœ±}°±~9X',·å\˜Ž_ñš*¼ô´Y^»‹zë„<7€SoâÍàÞTø øgZ¯æI\oW]Ò„ÞN=åK|y§Ù¬ðlÒýÙàeà5\ëRÈz5b½µ^’xQâEεà¢õìø”9gÇün•u|þë­‰†xÚMQKRÂ@íù@!‚°ñƒ-.L Êr‘x–!Œ&2©™!7ðr 7ðr¯ÀÎNª˜ª®ééÏë×o$T§Ž¶@ã @ÍT´†>3ÍVäH°±JÓ5æéáBãzLRƒSÖÕ6@-´!+ö ?ðF¡U¾ç¬„Û‡Aßëè]Œ-X‰Û… ï©¬HŒÎ&*s˜X2AíÁ“æ¹ÅÈŠa$Ø®Y­j<¤è’‰*BS–ny”w€<®F.Ñ™íñ:m…ÓÞF§ i8R©õ߬Άü³Òdd缃éF¹½L’»ïR=­]…ØfÐ)Z,€T‰µuöC0ª5Êê´ð#½lJáí[±p“¼³ o¡Bø¥úÄD€I\Ÿô_r¹6¾’ìuš†&qs¼â‡Usù-qDƪxÇoÂŽ¾_â¤ÁE?â¬b¸úOœÓÐXOTC^ŸÝËKòÖîY^ÜÎ왼&8;·Ÿòf»Ø¯¼%ÿäokwþxÚK`€€v Á¸Þ hxÚ5Ë=€0 @áò30` ؘê ந$PH @ n yÉò]ryÆÈL¸bªEW‰Q åÏÒ-ìA{L˜± ÓFÌØ7âˆ'zÜñÆ»VpÆ |ð²£/÷ €i cwl_utils-0.41/cwl_utils/image_puller.py0000644000000000000000000001075613615410400015420 0ustar00# SPDX-License-Identifier: Apache-2.0 """Classes for docker-extract.""" import logging import subprocess # nosec from abc import ABC, abstractmethod from pathlib import Path from .singularity import get_version as get_singularity_version from .singularity import is_version_2_6 as is_singularity_version_2_6 from .singularity import is_version_3_or_newer as is_singularity_version_3_or_newer logging.basicConfig(level=logging.INFO) _LOGGER = logging.getLogger(__name__) class ImagePuller(ABC): def __init__( self, req: str, save_directory: str | Path | None, cmd: str, force_pull: bool, ) -> None: """Create an ImagePuller.""" self.req = req self.save_directory = save_directory self.cmd = cmd self.force_pull = force_pull @abstractmethod def get_image_name(self) -> str: """Get the engine-specific image name.""" @abstractmethod def save_docker_image(self) -> None: """Download and save the image to disk.""" @staticmethod def _run_command_pull(cmd_pull: list[str]) -> None: try: subprocess.run( # nosec cmd_pull, check=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT ) except subprocess.CalledProcessError as err: if err.output: raise subprocess.SubprocessError(err.output) from err raise err class DockerImagePuller(ImagePuller): """Pull docker image with Docker.""" def get_image_name(self) -> str: """Get the name of the tarball.""" # Replace colons with underscores in the name. # See https://github.com/containers/podman/issues/489 return ("".join(self.req.split("/")) + ".tar").replace(":", "_") def generate_udocker_loading_command(self) -> str: """Generate the udocker loading command.""" return f"udocker load -i {self.get_image_name()}" def save_docker_image(self) -> None: """Download and save the software container image to disk as a docker tarball.""" _LOGGER.info(f"Pulling {self.req} with {self.cmd}...") cmd_pull = [self.cmd, "pull", self.req] ImagePuller._run_command_pull(cmd_pull) _LOGGER.info(f"Image successfully pulled: {self.req}") if self.save_directory: dest = Path(self.save_directory, self.get_image_name()) if self.save_directory and self.force_pull: dest.unlink() cmd_save = [ self.cmd, "save", "-o", str(dest), self.req, ] subprocess.run(cmd_save, check=True) # nosec _LOGGER.info(f"Image successfully saved: {dest!r}.") print(self.generate_udocker_loading_command()) class SingularityImagePuller(ImagePuller): """Pull docker image with Singularity.""" CHARS_TO_REPLACE = ["/", ":"] NEW_CHAR = "_" def get_image_name(self) -> str: """Determine the file name appropriate to the installed version of Singularity.""" image_name = self.req for char in self.CHARS_TO_REPLACE: image_name = image_name.replace(char, self.NEW_CHAR) if is_singularity_version_2_6(): suffix = ".img" elif is_singularity_version_3_or_newer(): suffix = ".sif" else: raise Exception( f"Don't know how to handle this version of singularity: {get_singularity_version()}." ) return f"{image_name}{suffix}" def save_docker_image(self) -> None: """Pull down the Docker software container image and save it in the Singularity image format.""" save_directory: str | Path if self.save_directory: save_directory = self.save_directory target = Path(save_directory, self.get_image_name()) if target.exists() and not self.force_pull: _LOGGER.info(f"Already cached {self.req} with Singularity.") return _LOGGER.info(f"Pulling {self.req} with Singularity...") cmd_pull = [ self.cmd, "pull", ] if self.force_pull: cmd_pull.append("--force") cmd_pull.extend( [ "--name", str(target), f"docker://{self.req}", ] ) ImagePuller._run_command_pull(cmd_pull) _LOGGER.info( f"Image successfully pulled: {save_directory}/{self.get_image_name()}" ) cwl_utils-0.41/cwl_utils/inputs_schema_gen.py0000644000000000000000000004732313615410400016446 0ustar00#!/usr/bin/env python3 # SPDX-License-Identifier: Apache-2.0 # Copyright 2024 Hirotaka Suetake # Copyright 2024 Alexis Lucattini """Generate JSON Schema from CWL inputs object.""" import argparse import json import logging import sys from contextlib import suppress from copy import deepcopy from importlib.resources import files from pathlib import Path from typing import Any, TypeGuard from urllib.parse import urlparse import requests from cwl_utils.loghandler import _logger as _cwlutilslogger from cwl_utils.parser import ( CommandLineTool, Directory, File, InputArraySchema, InputEnumSchema, InputRecordSchema, InputRecordSchemaTypes, Workflow, WorkflowInputParameter, cwl_v1_0, cwl_v1_1, cwl_v1_2, load_document_by_uri, ) from cwl_utils.utils import ( get_value_from_uri, is_local_uri, is_uri, sanitise_schema_field, to_pascal_case, ) _logger = logging.getLogger("cwl-inputs-schema-gen") # pylint: disable=invalid-name defaultStreamHandler = logging.StreamHandler() # pylint: disable=invalid-name _logger.addHandler(defaultStreamHandler) _logger.setLevel(logging.INFO) _cwlutilslogger.setLevel(100) # Globals # Maps CWL types to JSON Schema types PRIMITIVE_TYPES_MAPPING = { "boolean": "boolean", "string": "string", "int": "integer", "float": "number", "long": "number", "double": "number", "null": "null", } # Some type hinting InputType = ( InputArraySchema | InputEnumSchema | InputRecordSchema | str | File | Directory ) # Don't need type checking at runtime class JSONSchemaProperty: """Generate a JSON schema property from a CWL input parameter.""" def __init__( self, name: str, type_: InputType | list[InputType] | str | Any, description: str | None = "", required: bool | None = False, ): """Initialise the JSONSchemaProperty object.""" # Initialise values self.name: str = name self.type_: InputType | list[InputType] | str | Any = type_ self.description = description self.required = required self.type_dict = self.generate_type_dict() def generate_type_dict(self) -> dict[str, Any]: """Generate the type dict for a property from a CWL input parameter type.""" # If the type is a list and contains null, then the property is not required if isinstance(self.type_, list) and "null" in self.type_: self.required = False self.type_ = list(filter(lambda type_item: type_item != "null", self.type_)) # Check if we're down to one item, we can then squeeze if len(self.type_) == 1: self.type_ = self.type_[0] # type_ is still a list therefore we offer multiple input types for this parameter if isinstance(self.type_, list): # We use the oneOf keyword to specify multiple types type_dict = self.generate_type_dict_from_type_list(self.type_) # type_ is a single type else: type_dict = self.generate_type_dict_from_type(self.type_) # Add in the description to the type dict type_dict.update({"description": self.description}) return type_dict def generate_type_dict_from_type(self, type_item: Any) -> dict[str, Any]: """ Generate the type dict for a property from a CWL input parameter type. We call this function for each type in the type_ list In the case there are multiple types, each dict is added to the oneOf list """ # Primitive types should have a 1-1 mapping # Between an CWL Input Parameter type and a JSON schema type match type_item: case str(key) if key in PRIMITIVE_TYPES_MAPPING: return {"type": PRIMITIVE_TYPES_MAPPING[key]} case "stdin": return {"$ref": "#/definitions/File"} case "File" | "Directory" | "Any": return {"$ref": f"#/definitions/{type_item}"} # When item is a record schema type case str() if is_uri(type_item): return { "$ref": f"#/definitions/{to_pascal_case(get_value_from_uri(type_item))}" } case str(): raise ValueError(f"Unknown type: {type_item}") case ( cwl_v1_0.InputArraySchema() | cwl_v1_1.InputArraySchema() | cwl_v1_2.InputArraySchema() ): return { "type": "array", "items": self.generate_type_dict_from_type(type_item.items), } case ( cwl_v1_0.InputEnumSchema() | cwl_v1_1.InputEnumSchema() | cwl_v1_2.InputEnumSchema() ): return { "type": "string", "enum": list( map( get_value_from_uri, type_item.symbols, ) ), } case ( cwl_v1_0.InputRecordSchema(fields=f) | cwl_v1_1.InputRecordSchema(fields=f) | cwl_v1_2.InputRecordSchema(fields=f) ): match f: case None: return {"type": "object"} case list(fields): return { "type": "object", "properties": { get_value_from_uri( prop.name ): self.generate_type_dict_from_type(prop.type_) for prop in fields }, } case _: _cwlutilslogger.error( "Expected fields of InputRecordSchemaType to be a list" ) raise TypeError case {"$import": uri}: # This path is a relative path to import return { "$ref": f"#/definitions/{to_pascal_case(get_value_from_uri(uri))}" } # Nested import # {'$import': '../relative/path/to/schema'} case dict(): raise ValueError(f"Unknown type: {type_item}") case list(): # Nested schema return { "oneOf": list( map( self.generate_type_dict_from_type, type_item, ) ) } case _: raise ValueError(f"Unknown type: {type_item}") def generate_type_dict_from_type_list( self, type_: list[InputType] ) -> dict[str, Any]: """Given a list of types, generate a JSON schema property dict wrapped in oneOf list.""" return { "oneOf": list( map( self.generate_type_dict_from_type, type_, ) ) } def to_dict(self) -> dict[str, Any]: """Return as a dictionary.""" return {self.name: self.type_dict} def get_is_required_from_input_parameter( input_parameter: WorkflowInputParameter, ) -> bool: """Given an input parameter, return if it is required.""" if isinstance(input_parameter.type_, str) and input_parameter.type_.endswith("?"): return False if input_parameter.default is not None: return False if isinstance(input_parameter.type_, list) and "null" in input_parameter.type_: return False if isinstance(input_parameter.type_, InputRecordSchemaTypes): if input_parameter.type_ is not None: if (isinstance(input_parameter.type_.type_, str)) and ( input_parameter.type_.type_.endswith("?") ): return False return True def generate_json_schema_property_from_input_parameter( input_parameter: WorkflowInputParameter, ) -> JSONSchemaProperty: """ Given an input parameter, generate a JSON schema property. :param input_parameter: :return: """ # Get the input name and documentation for description input_name = get_value_from_uri(str(input_parameter.id)) doc = input_parameter.doc required = get_is_required_from_input_parameter(input_parameter) return JSONSchemaProperty( name=input_name, type_=input_parameter.type_, description=doc if doc is not None else "", required=required, ) def generate_definition_from_schema(schema: InputRecordSchema) -> dict[str, Any]: """ Given a schema, generate a JSON schema definition. :param schema: :return: """ # Sanitise each field of the schema sanitised_fields = {} if schema.fields is None: return {} for field in schema.fields: sanitised_fields.update( { get_value_from_uri(field.name): sanitise_schema_field( {"type": field.type_} ) } ) # Generate JSON properties property_list = [] for prop_name, prop_obj in sanitised_fields.items(): # Simplify type first by removing nulls required = True # If the property object is a string, then it's a reference to another schema if isinstance(prop_obj, str): raise TypeError("Property Object should be a dictionary") if isinstance(prop_obj.get("type", []), list): if "null" in prop_obj.get("type", []): required = False prop_obj["type"] = list( filter(lambda type_item: type_item != "null", prop_obj.get("type", [])) ) # Check if we're down to one item if len(prop_obj["type"]) == 1: prop_obj["type"] = prop_obj["type"][0] # Generate JSONSchema Property prop = JSONSchemaProperty( name=prop_name, type_=prop_obj.get("type"), description=prop_obj.get("doc", ""), required=required, ) property_list.append(prop) return { to_pascal_case(get_value_from_uri(str(schema.name))): { "type": "object", "properties": {prop.name: prop.type_dict for prop in property_list}, "required": [prop.name for prop in property_list if prop.required], } } def cwl_to_jsonschema(cwl_obj: Workflow | CommandLineTool) -> Any: """ cwl_obj: A CWL Object. Returns: A JSONSchema object. Example: cwl_obj = load_document_by_uri() jsonschema = cwl_to_jsonschema(cwl_inputs) """ # Initialise the schema from the workflow input json schema template with ( files("cwl_utils") .joinpath("./templates/workflow_input_json_schema_template.json") .open() as template_h ): input_json_schema = json.load(template_h) # Get the complex schema keys def is_complex_record_schema_key(idx_iter: str) -> TypeGuard[bool]: if cwl_obj.loadingOptions.idx is None: return False if cwl_obj.loadingOptions.idx.get(idx_iter) is None: return False if not isinstance(cwl_obj.loadingOptions.idx.get(idx_iter), tuple): return False # Get index as a tuple input_schema_type, _ = cwl_obj.loadingOptions.idx.get(idx_iter, (None, None)) if isinstance(input_schema_type, InputRecordSchemaTypes): return True return False complex_schema_keys: list[str] = list( filter( is_complex_record_schema_key, cwl_obj.loadingOptions.idx.keys(), ) ) # Complex schema values def get_complex_schema_values(idx_iter: str) -> InputRecordSchema: if not isinstance(cwl_obj.loadingOptions.idx.get(idx_iter), tuple): raise TypeError(f"Expected tuple from idx loading options key {idx_iter}") # Collect input record schema input_record_schema, _ = cwl_obj.loadingOptions.idx.get(idx_iter, (None, None)) if not isinstance(input_record_schema, InputRecordSchemaTypes): raise TypeError( f"Expected InputRecordSchemaTypes from idx loading options key {idx_iter}" ) return input_record_schema complex_schema_values: list[InputRecordSchema] = list( map( get_complex_schema_values, complex_schema_keys, ) ) # Load in all $imports to be referred by complex input types workflow_schema_definitions_list = list( map( generate_definition_from_schema, complex_schema_values, ) ) if cwl_obj.requirements is not None: with suppress(StopIteration): schema_def_requirement = next( filter( lambda requirement_iter: requirement_iter.class_ == "SchemaDefRequirement", cwl_obj.requirements, ) ) workflow_schema_definitions_list.extend( list( map( generate_definition_from_schema, schema_def_requirement.types, ) ) ) # Convert schema definitions to dict workflow_schema_definitions_dict = {} for schema_definition in workflow_schema_definitions_list: workflow_schema_definitions_dict.update(schema_definition) # Generate JSON Schema Properties properties = list( map( generate_json_schema_property_from_input_parameter, cwl_obj.inputs, ) ) # Generate JSON schema input_json_schema.update( { "type": "object", "properties": { prop.name: ( {"oneOf": [{"type": "null"}, prop.type_dict]} if prop.required is False else prop.type_dict ) for prop in properties }, "required": [prop.name for prop in properties if prop.required], } ) # Update definitions from schema input_json_schema["definitions"].update(workflow_schema_definitions_dict) # Slim down the schema as required input_json_schema = slim_definitions(input_json_schema) # Add "additionalProperties": false to top of schema # input_json_schema["additionalProperties"] = False return input_json_schema # Traverse the properties and return all definitions that are used def _recursive_search( json_data: dict[str, Any], target_key: str, ) -> list[Any]: """Given a target key return all instances of a key in a json object.""" result = [] if isinstance(json_data, dict): for key, value in json_data.items(): if key == target_key: result.append(value) else: result.extend(_recursive_search(value, target_key)) elif isinstance(json_data, list): for item in json_data: result.extend(_recursive_search(item, target_key)) return result # Get all the property dependencies def _get_all_ref_attributes(json_object: dict[str, Any]) -> list[Any]: """Given a json object, return all the reference attributes.""" return _recursive_search(json_object, "$ref") def get_property_dependencies( property_dict: dict[str, Any], input_json_schema: dict[str, Any], existing_property_dependencies: list[Any] | None = None, ) -> list[str]: """Recursively collect all dependencies for a property.""" # Initialise return list if existing_property_dependencies is None: existing_property_dependencies = [] # All reference attributes for reference_attribute in _get_all_ref_attributes(property_dict): # Get the value from the reference attribute reference_value = get_value_from_uri(reference_attribute) # If the reference value is not in the existing property dependencies, add it if reference_value not in existing_property_dependencies: existing_property_dependencies.append(reference_value) # Get the property dependencies of the reference value existing_property_dependencies.extend( get_property_dependencies( input_json_schema["definitions"][reference_value], input_json_schema, existing_property_dependencies, ) ) return existing_property_dependencies def slim_definitions(input_json_schema: dict[str, Any]) -> dict[str, Any]: """ Slim down the schema to only the definitions that are used by the properties. Traverse the properties and return all definitions that are used. Remove all other definitions. """ # Copy schema input_json_schema = deepcopy(input_json_schema) # Get required definitions required_definitions = get_property_dependencies( input_json_schema.get("properties", {}), input_json_schema ) for definition_key in list(input_json_schema["definitions"].keys()): if definition_key not in required_definitions: del input_json_schema["definitions"][definition_key] return input_json_schema def arg_parser() -> argparse.ArgumentParser: """Build the argument parser.""" parser = argparse.ArgumentParser(description="Generate JSON Schema from a CWL URI.") parser.add_argument("cwl_url", help="URL or Path to the CWL document") parser.add_argument( "-o", "--output", type=argparse.FileType("w"), default=sys.stdout, help="Output file. Default is stdout.", ) return parser def parse_args(args: list[str]) -> argparse.Namespace: """Parse the command line arguments.""" return arg_parser().parse_args(args) def main() -> None: """Console entry point.""" sys.exit(run(parse_args(sys.argv[1:]))) def get_cwl_url(url: str) -> str: """ Conform to uri format. If no scheme, then assert is a local file path and exists if scheme is file, then assert is a local file path and exists If scheme is not file, then assert is a valid Web URL Return either the url or the local path as a uri. """ if not is_uri(url): if not Path(url).exists(): logging.error("The CWL URL is invalid.") raise FileNotFoundError return Path(url).as_uri() elif is_local_uri(url): if not Path(urlparse(url).path).exists(): logging.error("The CWL URL is invalid.") raise FileNotFoundError return url else: # urlparse(url).scheme not in ['file']: response = requests.get(url, timeout=20) if response.status_code != 200: logging.error("The CWL URL is invalid.") raise FileNotFoundError return url def run(args: argparse.Namespace) -> int: """Run the main program.""" # Check the cwl_url is valid cwl_url = get_cwl_url(args.cwl_url) # Check the output file is writable if args.output.name != "": if not Path(args.output.name).parent.is_dir(): logging.error( "The output file is not writable, the output parent directory does not exist" ) return 1 _logger.info("Loading the CWL document") cwl_obj = load_document_by_uri(cwl_url) try: jsonschema = cwl_to_jsonschema(cwl_obj) except Exception as e: _logger.exception( "Failed to generate JSON Schema from CWL inputs object. Error: %s", e ) return 1 args.output.write(json.dumps(jsonschema, indent=2) + "\n") return 0 if __name__ == "__main__": main() cwl_utils-0.41/cwl_utils/loghandler.py0000644000000000000000000000046413615410400015065 0ustar00# SPDX-License-Identifier: Apache-2.0 """Shared logging object.""" import logging _logger = logging.getLogger("cwl_utils") # pylint: disable=invalid-name defaultStreamHandler = logging.StreamHandler() # pylint: disable=invalid-name _logger.addHandler(defaultStreamHandler) _logger.setLevel(logging.INFO) cwl_utils-0.41/cwl_utils/normalizer.py0000644000000000000000000001064113615410400015126 0ustar00#!/usr/bin/env python3 # SPDX-License-Identifier: Apache-2.0 # Copyright 2021 Michael R. Crusoe """Normalize CWL documents to CWL v1.2, JSON style.""" import argparse import logging import sys import tempfile from collections.abc import MutableSequence from pathlib import Path from cwlupgrader import main as cwlupgrader from ruamel import yaml from schema_salad.sourceline import add_lc_filename from cwl_utils import cwl_v1_2_expression_refactor from cwl_utils.loghandler import _logger as _cwlutilslogger from cwl_utils.pack import pack from cwl_utils.parser.cwl_v1_2 import load_document_by_yaml, save _logger = logging.getLogger("cwl-normalizer") # pylint: disable=invalid-name defaultStreamHandler = logging.StreamHandler() # pylint: disable=invalid-name _logger.addHandler(defaultStreamHandler) _logger.setLevel(logging.INFO) _cwlutilslogger.setLevel(100) def arg_parser() -> argparse.ArgumentParser: """Build the argument parser.""" parser = argparse.ArgumentParser( description="Normalizes CWL documents. Will upgrade to CWL v1.2, " "and pack the result. Can optionally refactor out CWL expressions." ) parser.add_argument( "--etools", help="Output ExpressionTools, don't go all the way to CommandLineTools.", action="store_true", ) parser.add_argument( "--skip-some1", help="Don't process CommandLineTool.inputs.inputBinding and CommandLineTool.arguments sections.", action="store_true", ) parser.add_argument( "--skip-some2", help="Don't process CommandLineTool.outputEval or " "CommandLineTool.requirements.InitialWorkDirRequirement.", action="store_true", ) parser.add_argument( "--no-expression-refactoring", help="Don't do any CWL expression refactoring.", action="store_true", ) parser.add_argument("dir", help="Directory in which to save converted files") parser.add_argument( "inputs", nargs="+", help="One or more CWL documents.", ) return parser def parse_args(args: list[str]) -> argparse.Namespace: """Parse the command line arguments.""" return arg_parser().parse_args(args) def main() -> None: """Console entry point.""" sys.exit(run(parse_args(sys.argv[1:]))) def run(args: argparse.Namespace) -> int: """Primary processing loop.""" imports: set[str] = set() for document in args.inputs: _logger.info("Processing %s.", document) with open(document) as doc_handle: result = yaml.main.round_trip_load(doc_handle, preserve_quotes=True) add_lc_filename(result, document) version = result.get("cwlVersion", None) if version in ("draft-3", "cwl:draft-3", "v1.0", "v1.1"): result = cwlupgrader.upgrade_document(result, args.dir, imports=imports) else: _logger.error( "Sorry, %s in %s is not a supported CWL version by this tool.", (version, document), ) return -1 uri = Path(document).resolve().as_uri() if not args.no_expression_refactoring: refactored, _ = cwl_v1_2_expression_refactor.traverse( load_document_by_yaml(result, uri), not args.etools, False, args.skip_some1, args.skip_some2, ) if not isinstance(refactored, MutableSequence): result = save( refactored, base_url=(refactored.loadingOptions.fileuri or ""), ) # ^^ Setting the base_url and keeping the default value # for relative_uris=True means that the IDs in the generated # JSON/YAML are kept clean of the path to the input document else: result = [ save(result_item, base_url=result_item.loadingOptions.fileuri) for result_item in refactored ] if "$graph" in result: packed = result else: with tempfile.TemporaryDirectory() as tmpdirname: path = Path(tmpdirname) / Path(document).name packed = pack(str(path)) output = Path(args.dir) / Path(document).name with output.open("w", encoding="utf-8") as output_filehandle: output_filehandle.write(packed) return 0 if __name__ == "__main__": main() cwl_utils-0.41/cwl_utils/pack.py0000644000000000000000000002115113615410400013660 0ustar00# SPDX-License-Identifier: Apache-2.0 # Copyright (c) 2021 Michael R. Crusoe # Copyright (c) 2020 Seven Bridges # See https://github.com/rabix/sbpack/blob/b8404a0859ffcbe1edae6d8f934e51847b003320/LICENSE """ CWL document packing functions. The link resolution is as follows: We always have two components: the base and the link If the link is a url or absolute path it is what is used to fetch the data. If the link is a relative path it is combined with the base and that is what is used to fetch data From https://github.com/rabix/sbpack/blob/b8404a0859ffcbe1edae6d8f934e51847b003320/sbpack/lib.py """ import logging import sys import urllib.parse import urllib.request from collections.abc import ItemsView from typing import TYPE_CHECKING, Any, Union, cast from packaging import version from cwl_utils import schemadef, utils if TYPE_CHECKING: from _collections_abc import dict_items logger = logging.getLogger(__name__) def get_inner_dict( cwl: dict[str, Any], path: list[dict[str, Any]] ) -> dict[str, Any] | None: if not path: return cwl if isinstance(cwl, dict): _v = cwl.get(path[0]["key"]) if _v is not None: return get_inner_dict(_v, path[1:]) elif isinstance(cwl, list): # Going to assume this is a map expressed as list for _v in cwl: if isinstance(_v, dict): if _v.get(path[0]["key_field"]) == path[0]["key"]: return get_inner_dict(_v, path[1:]) return None def pack_process( cwl: dict[str, Any], base_url: urllib.parse.ParseResult, cwl_version: str, parent_user_defined_types: dict[str, Any] | None = None, ) -> dict[str, Any]: cwl = listify_everything(cwl) cwl = normalize_sources(cwl) cwl, user_defined_types = load_schemadefs(cwl, base_url, parent_user_defined_types) cwl = resolve_schemadefs(cwl, base_url, user_defined_types) cwl = resolve_imports(cwl, base_url) cwl = resolve_steps( cwl, base_url, cwl.get("cwlVersion", cwl_version), user_defined_types, ) cwl = add_missing_requirements(cwl) return cwl def listify_everything(cwl: dict[str, Any]) -> dict[str, Any]: """ Convert many CWL construct from their map to the list version. See https://www.commonwl.org/v1.1/Workflow.html#map """ for port in ("inputs", "outputs"): cwl[port] = utils.normalize_to_list( cwl.get(port, []), key_field="id", value_field="type" ) cwl["requirements"] = utils.normalize_to_list( cwl.get("requirements", []), key_field="class", value_field=None ) if cwl.get("class") != "Workflow": return cwl cwl["steps"] = utils.normalize_to_list( cwl.get("steps", []), key_field="id", value_field=None ) for _, v in enumerate(cwl["steps"]): if isinstance(v, dict): v["in"] = utils.normalize_to_list( v.get("in", []), key_field="id", value_field="source" ) return cwl def normalize_sources(cwl: dict[str, Any]) -> dict[str, Any]: """Normalize the steps and output of a CWL Workflow.""" if cwl.get("class") != "Workflow": return cwl for _step in cwl.get("steps", {}): if not isinstance(_step, dict): continue _inputs = _step.get("in", {}) for k, _input in enumerate(_inputs): if isinstance(_input, str): _inputs[k] = _normalize(_input) elif isinstance(_input, dict): _src = _input.get("source") if isinstance(_src, str): _input["source"] = _normalize(_input["source"]) _outputs = cwl.get("outputs", {}) for k, _output in enumerate(_outputs): if isinstance(_output, str): _outputs[k] = _normalize(_output) elif isinstance(_output, dict): _src = _output.get("outputSource") if isinstance(_src, str): _output["outputSource"] = _normalize(_output["outputSource"]) return cwl def _normalize(s: str) -> str: if s.startswith("#"): return s[1:] return s def load_schemadefs( cwl: dict[str, Any], base_url: urllib.parse.ParseResult, parent_user_defined_types: dict[str, Any] | None = None, ) -> tuple[dict[str, Any], dict[str, Any]]: """Internalize any SchemaDefRequirement, and remove it.""" user_defined_types = schemadef.build_user_defined_type_dict(cwl, base_url) if parent_user_defined_types is not None: user_defined_types.update(parent_user_defined_types) cwl["requirements"] = [ req for req in cwl.get("requirements", []) if req.get("class") != "SchemaDefRequirement" ] return cwl, user_defined_types def resolve_schemadefs( cwl: dict[str, Any], base_url: urllib.parse.ParseResult, user_defined_types: dict[str, Any], ) -> dict[str, Any]: cwl = schemadef.inline_types(cwl, "inputs", base_url, user_defined_types) cwl = schemadef.inline_types(cwl, "outputs", base_url, user_defined_types) return cwl def resolve_imports(cwl: Any, base_url: urllib.parse.ParseResult) -> Any: if isinstance(cwl, dict): itr: Union["dict_items[Any, Any]", ItemsView[Any, Any]] = cwl.items() elif isinstance(cwl, list): itr = cast(ItemsView[Any, Any], [(n, v) for n, v in enumerate(cwl)]) else: return cwl for k, v in itr: if isinstance(v, dict): if len(v) == 1: _k = list(v.keys())[0] if _k in ("$import", "$include"): cwl[k], this_base_url = utils.load_linked_file( base_url, v[_k], is_import=_k == "$import" ) cwl[k] = resolve_imports(cwl[k], base_url) return cwl def resolve_steps( cwl: dict[str, Any], base_url: urllib.parse.ParseResult, cwl_version: str, parent_user_defined_types: dict[str, Any] | None = None, ) -> dict[str, Any]: """Load and pack all "run" sections of the workflow steps.""" if isinstance(cwl, str): raise RuntimeError(f"{base_url.geturl()}: Expecting a process, found a string") if not isinstance(cwl, dict): return cwl if cwl.get("class") != "Workflow": return cwl for _, v in enumerate(cwl["steps"]): if isinstance(v, dict): sys.stderr.write( f"\n--\nRecursing into step {base_url.geturl()}:{v['id']}\n" ) _run = v.get("run") if isinstance(_run, str): v["run"], new_base_url = utils.load_linked_file( base_url, _run, is_import=True ) v["run"] = pack_process( v["run"], new_base_url, cwl.get("cwlVersion", cwl_version), ) else: v["run"] = pack_process( v["run"], base_url, cwl.get("cwlVersion", cwl_version), parent_user_defined_types, ) if "cwlVersion" in v["run"]: parent_version = version.parse( cwl.get("cwlVersion", cwl_version).strip("v") ) this_version = version.parse(v["run"]["cwlVersion"].strip("v")) if this_version > parent_version: cwl["cwlVersion"] = v["run"]["cwlVersion"] # not really enough, but hope for the best return cwl def add_missing_requirements(cwl: dict[str, Any]) -> dict[str, Any]: """Due to packing, we may need to add a "SubworkflowFeatureRequirement".""" requirements = cwl.get("requirements", []) present = {req["class"] for req in requirements} def _add_req(_req_name: str) -> None: nonlocal requirements if _req_name not in present: requirements += [{"class": _req_name}] if cwl.get("class") == "Workflow": sub_workflow = False for step in cwl["steps"]: if step["run"]["class"] == "Workflow": sub_workflow = True break if sub_workflow: _add_req("SubworkflowFeatureRequirement") return cwl def pack(cwl_path: str) -> dict[str, Any]: """Pack a CWL document at the given path.""" sys.stderr.write(f"Packing {cwl_path}\n") file_path_url = urllib.parse.urlparse(cwl_path) cwl, full_url = cast( tuple[dict[str, Any], urllib.parse.ParseResult], utils.load_linked_file(base_url=file_path_url, link="", is_import=True), ) if "$graph" in cwl: # assume already packed return cwl cwl = pack_process(cwl, full_url, cwl["cwlVersion"]) return cwl cwl_utils-0.41/cwl_utils/py.typed0000644000000000000000000000000013615410400014055 0ustar00cwl_utils-0.41/cwl_utils/sandboxjs.py0000644000000000000000000006175213615410400014750 0ustar00# SPDX-License-Identifier: Apache-2.0 """Safe execution of CWL Expressions in a NodeJS sandbox.""" import collections import errno import glob import json import os import re import select import subprocess # nosec import threading from abc import ABC, abstractmethod from collections.abc import Awaitable, Mapping, MutableMapping, MutableSequence from contextlib import suppress from importlib.resources import files from io import BytesIO from pathlib import Path from typing import Any, Deque, cast from schema_salad.utils import json_dumps from cwl_utils.errors import JavascriptException, WorkflowException from cwl_utils.loghandler import _logger from cwl_utils.types import ( CWLOutputType, is_directory, is_directory_key, is_file, is_file_key, ) from cwl_utils.utils import singularity_supports_userns default_timeout: float = 20 """Default number of seconds to wait while running a javascript engine.""" seg_symbol = r"""\w+""" seg_single = r"""\['([^']|\\')+'\]""" seg_double = r"""\["([^"]|\\")+"\]""" seg_index = r"""\[[0-9]+\]""" segments = rf"(\.{seg_symbol}|{seg_single}|{seg_double}|{seg_index})" segment_re = re.compile(segments, flags=re.UNICODE) param_str = rf"\(({seg_symbol}){segments}*\)$" param_re = re.compile(param_str, flags=re.UNICODE) def code_fragment_to_js(jscript: str, jslib: str = "") -> str: if isinstance(jscript, str) and len(jscript) > 1 and jscript[0] == "{": inner_js = jscript else: inner_js = "{return (%s);}" % jscript return f'"use strict";\n{jslib}\n(function(){inner_js})()' def linenum(fn: str) -> str: lines = fn.splitlines() ofs = 0 maxlines = 99 if len(lines) > maxlines: ofs = len(lines) - maxlines lines = lines[-maxlines:] return "\n".join("%02i %s" % (i + ofs + 1, b) for i, b in enumerate(lines)) def stdfmt(data: str) -> str: if "\n" in data: return "\n" + data.strip() return data class JSEngine(ABC): @abstractmethod def eval( self, scan: str, jslib: str = "", timeout: float = default_timeout, force_docker_pull: bool = False, debug: bool = False, js_console: bool = False, container_engine: str = "docker", **kwargs: Any, ) -> CWLOutputType | Awaitable[CWLOutputType]: ... @abstractmethod def regex_eval( self, parsed_string: str, remaining_string: str, current_value: CWLOutputType, **kwargs: Any, ) -> CWLOutputType | Awaitable[CWLOutputType]: ... class NodeJSEngine(JSEngine): localdata = threading.local() def __init__( self, have_node_slim: bool = False, minimum_node_version_str: str = "0.10.26", process_finished_str: str = "r1cepzbhUTxtykz5XTC4\n", ): self.have_node_slim: bool = have_node_slim self.minimum_node_version_str: str = minimum_node_version_str self.process_finished_str: str = process_finished_str self.processes_to_kill: Deque[subprocess.Popen[str]] = collections.deque() def __del__(self) -> None: with suppress(TypeError): while self.processes_to_kill: process = self.processes_to_kill.popleft() if isinstance(process.args, MutableSequence): args = process.args else: args = [process.args] cidfile = [ str(arg).split("=")[1] for arg in args if "--cidfile" in str(arg) ] if cidfile: # Try to be nice with suppress(FileNotFoundError): with open(cidfile[0]) as inp_stream: p = subprocess.Popen( # nosec [args[0], "kill", inp_stream.read()], shell=False, # nosec ) try: p.wait(timeout=10) except subprocess.TimeoutExpired: p.kill() if process.stdin: process.stdin.close() with suppress(subprocess.TimeoutExpired): process.wait(10) process.kill() def check_js_threshold_version(self, working_alias: str) -> bool: """ Check if the nodeJS engine version on the system with the allowed minimum version. https://github.com/nodejs/node/blob/master/CHANGELOG.md#nodejs-changelog """ # parse nodejs version into int Tuple: 'v4.2.6\n' -> [4, 2, 6] current_version_str = subprocess.check_output( # nosec [working_alias, "-v"], text=True ) current_version = [ int(v) for v in current_version_str.strip().strip("v").split(".") ] minimum_node_version = [ int(v) for v in self.minimum_node_version_str.split(".") ] return current_version >= minimum_node_version def exec_js_process( self, js_text: str, timeout: float = default_timeout, js_console: bool = False, context: str | None = None, force_docker_pull: bool = False, container_engine: str = "docker", ) -> tuple[int, str, str]: """ Run a javascript text. :param timeout: Max number of seconds to wait. :returns: A tuple of the return code, stdout, and stderr of the javascript engine invocation. """ if not hasattr(self.localdata, "procs"): self.localdata.procs = {} if js_console and context is not None: raise NotImplementedError("js_console=True and context not implemented") if js_console: js_engine = "cwlNodeEngineJSConsole.js" _logger.warning( "Running with support for javascript console in expressions (DO NOT USE IN PRODUCTION)" ) elif context is not None: js_engine = "cwlNodeEngineWithContext.js" else: js_engine = "cwlNodeEngine.js" created_new_process = False if context is not None: nodejs = self.localdata.procs.get((js_engine, context)) else: nodejs = self.localdata.procs.get(js_engine) if nodejs is None or nodejs.poll() is not None: js_engine_code = files("cwl_utils").joinpath(js_engine).read_text("utf-8") created_new_process = True new_proc = self.new_js_proc( js_engine_code, force_docker_pull=force_docker_pull, container_engine=container_engine, ) if context is None: self.localdata.procs[js_engine] = new_proc nodejs = new_proc else: self.localdata.procs[(js_engine, context)] = new_proc nodejs = new_proc killed = [] def terminate() -> None: """Kill the node process if it exceeds timeout limit.""" with suppress(OSError): killed.append(True) nodejs.kill() timer = threading.Timer(timeout, terminate) timer.daemon = True timer.start() stdin_text = "" if created_new_process and context is not None: stdin_text = json_dumps(context) + "\n" stdin_text += json_dumps(js_text) + "\n" stdin_buf = BytesIO(stdin_text.encode("utf-8")) stdout_buf = BytesIO() stderr_buf = BytesIO() rselect: list[BytesIO] = [nodejs.stdout, nodejs.stderr] wselect: list[BytesIO] = [nodejs.stdin] def process_finished() -> bool: return stdout_buf.getvalue().decode("utf-8").endswith( self.process_finished_str ) and stderr_buf.getvalue().decode("utf-8").endswith( self.process_finished_str ) while not process_finished() and timer.is_alive(): rready, wready, _ = select.select(rselect, wselect, []) try: if nodejs.stdin in wready: buf = stdin_buf.read(select.PIPE_BUF) if buf: os.write(nodejs.stdin.fileno(), buf) for pipes in ((nodejs.stdout, stdout_buf), (nodejs.stderr, stderr_buf)): if pipes[0] in rready: buf = os.read(pipes[0].fileno(), select.PIPE_BUF) if buf: pipes[1].write(buf) except OSError: break timer.cancel() stdin_buf.close() stdoutdata = stdout_buf.getvalue()[: -len(self.process_finished_str) - 1] stderrdata = stderr_buf.getvalue()[: -len(self.process_finished_str) - 1] nodejs.poll() if nodejs.poll() not in (None, 0): if killed: returncode = -1 else: returncode = nodejs.returncode else: returncode = 0 return returncode, stdoutdata.decode("utf-8"), stderrdata.decode("utf-8") def new_js_proc( self, js_text: str, force_docker_pull: bool = False, container_engine: str = "docker", ) -> "subprocess.Popen[str]": """Return a subprocess ready to submit javascript to.""" required_node_version, docker = (False,) * 2 nodejs: subprocess.Popen[str] | None = None trynodes = ("nodejs", "node") for n in trynodes: try: if ( subprocess.check_output( # nosec [n, "--eval", "process.stdout.write('t')"], text=True, ) != "t" ): continue else: nodejs = subprocess.Popen( # nosec [n, "--eval", js_text], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, ) self.processes_to_kill.append(nodejs) required_node_version = self.check_js_threshold_version(n) break except (subprocess.CalledProcessError, OSError): pass if nodejs is None or nodejs is not None and not required_node_version: try: nodeimg = "node:alpine" if container_engine == "singularity": nodeimg = f"docker://docker.io/{nodeimg}" elif container_engine in ("podman", "udocker"): nodeimg = f"docker.io/library/{nodeimg}" if not self.have_node_slim: singularity_cache: str | None = None match container_engine: case "docker" | "podman": dockerimgs = subprocess.check_output( # nosec [container_engine, "images", "-q", nodeimg], text=True, ) case "singularity": singularity_cache = os.environ.get("CWL_SINGULARITY_CACHE") if singularity_cache: singularityimgs = glob.glob( singularity_cache + "/node_alpine.sif" ) else: singularityimgs = glob.glob( str(Path.cwd() / "node_alpine.sif") ) if singularityimgs: nodeimg = singularityimgs[0] case "udocker": matches = re.search( re.escape(nodeimg), subprocess.check_output( # nosec [container_engine, "images"], text=True, ), ) if matches: dockerimgs = matches[0] else: dockerimgs = "" case _: raise Exception( f"Unknown container_engine: {container_engine}." ) # if output is an empty string need_singularity = ( container_engine == "singularity" and not singularityimgs ) need_docker = container_engine != "singularity" and ( len(dockerimgs.split("\n")) <= 1 ) if need_singularity or need_docker or force_docker_pull: # pull node:alpine docker container nodejs_pull_commands = [container_engine, "pull"] if force_docker_pull: nodejs_pull_commands.append("--force") nodejs_pull_commands.append(nodeimg) cwd = singularity_cache or Path.cwd() nodejsimg = subprocess.check_output( # nosec nodejs_pull_commands, text=True, cwd=str(cwd) ) _logger.debug( "Pulled Docker image %s %s using %s", nodeimg, nodejsimg, container_engine, ) self.have_node_slim = True nodejs_commands = [container_engine] if ( container_engine != "singularity" and "udocker" not in container_engine ): nodejs_commands.extend( [ "run", "--attach=STDIN", "--attach=STDOUT", "--attach=STDERR", "--sig-proxy=true", "--interactive", "--rm", ] ) elif "singularity" in container_engine: nodejs_commands.extend( [ "exec", "--contain", "--ipc", "--cleanenv", "--userns" if singularity_supports_userns() else "--pid", ] ) elif "udocker" in container_engine: nodejs_commands.extend( [ "run", "--device=/dev/stdin", "--device=/dev/stdout", "--device=/dev/stderr", ] ) nodejs_commands.extend( [ nodeimg, "node", "--eval", js_text, ], ) _logger.debug("Running nodejs via %s", nodejs_commands[:-1]) nodejs = subprocess.Popen( # nosec nodejs_commands, universal_newlines=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, ) self.processes_to_kill.append(nodejs) docker = True except OSError as e: if e.errno == errno.ENOENT: pass else: raise except subprocess.CalledProcessError as e: _logger.debug("Error while attempting to run nodejs: %s", e) # docker failed and nodejs not on system if nodejs is None: raise JavascriptException( "NodeJSEngine requires Node.js engine to evaluate and validate " "Javascript expressions, but couldn't find it. Tried {trynodes}, " f"{container_engine} run node:alpine".format( trynodes=", ".join(trynodes), container_engine=container_engine ) ) # docker failed, but nodejs is installed on system but the version is below the required version if not docker and not required_node_version: raise JavascriptException( "NodeJSEngine requires minimum v{} version of Node.js engine.".format( self.minimum_node_version_str ), "Try updating: https://docs.npmjs.com/getting-started/installing-node", ) return nodejs def eval( self, scan: str, jslib: str = "", timeout: float = default_timeout, force_docker_pull: bool = False, debug: bool = False, js_console: bool = False, container_engine: str = "docker", **kwargs: Any, ) -> CWLOutputType: fn = code_fragment_to_js(scan, jslib) returncode, stdout, stderr = self.exec_js_process( fn, timeout, js_console=js_console, force_docker_pull=force_docker_pull, container_engine=container_engine, ) if js_console: if stderr is not None: _logger.info("Javascript console output:") _logger.info("----------------------------------------") _logger.info( "\n".join( re.findall(r"^[[](?:log|err)[]].*$", stderr, flags=re.MULTILINE) ) ) _logger.info("----------------------------------------") if returncode != 0: if debug: info = ( "returncode was: %s\nscript was:\n%s\nstdout was: %s\nstderr was: %s\n" % (returncode, linenum(fn), stdfmt(stdout), stdfmt(stderr)) ) else: info = "Javascript expression was: {}\nstdout was: {}\nstderr was: {}".format( scan, stdfmt(stdout), stdfmt(stderr) ) if returncode == -1: raise JavascriptException( f"Long-running script killed after {timeout} seconds: {info}" ) else: raise JavascriptException(info) try: return cast(CWLOutputType, json.loads(stdout)) except ValueError as err: raise JavascriptException( "{}\nscript was:\n{}\nstdout was: '{}'\nstderr was: '{}'\n".format( err, linenum(fn), stdout, stderr ) ) from err def regex_eval( self, parsed_string: str, remaining_string: str, current_value: CWLOutputType, **kwargs: Any, ) -> CWLOutputType: if remaining_string: m = segment_re.match(remaining_string) if not m: return current_value next_segment_str = m.group(1) key: str | int | None = None if next_segment_str[0] == ".": key = next_segment_str[1:] elif next_segment_str[1] in ("'", '"'): key = next_segment_str[2:-2].replace("\\'", "'").replace('\\"', '"') if key is not None: if ( isinstance(current_value, MutableSequence) and key == "length" and not remaining_string[m.end(1) :] ): return len(current_value) if not isinstance(current_value, MutableMapping): raise WorkflowException( "%s is a %s, cannot index on string '%s'" % (parsed_string, type(current_value).__name__, key) ) if key not in current_value: raise WorkflowException( f"{parsed_string} does not contain key {key!r}." ) else: try: key = int(next_segment_str[1:-1]) except ValueError as v: raise WorkflowException(str(v)) from v if not isinstance(current_value, MutableSequence): raise WorkflowException( "%s is a %s, cannot index on int '%s'" % (parsed_string, type(current_value).__name__, key) ) if key and key >= len(current_value): raise WorkflowException( "%s list index %i out of range" % (parsed_string, key) ) if isinstance(current_value, Mapping): try: if is_directory(current_value) and is_directory_key(key): return self.regex_eval( parsed_string + remaining_string, remaining_string[m.end(1) :], cast( CWLOutputType, current_value[key], ), ) elif is_file(current_value) and is_file_key(key): return self.regex_eval( parsed_string + remaining_string, remaining_string[m.end(1) :], cast( CWLOutputType, current_value[key], ), ) else: return self.regex_eval( parsed_string + remaining_string, remaining_string[m.end(1) :], cast( CWLOutputType, cast(MutableMapping[str, Any], current_value)[ cast(str, key) ], ), ) except KeyError as exc: raise WorkflowException( f"{parsed_string!r} doesn't have property {key!r}." ) from exc elif isinstance(current_value, list) and isinstance(key, int): try: return self.regex_eval( parsed_string + remaining_string, remaining_string[m.end(1) :], current_value[key], ) except KeyError as exc: raise WorkflowException( f"{parsed_string!r} doesn't have property {key!r}." ) from exc else: raise WorkflowException( f"{parsed_string!r} doesn't have property {key!r}." ) else: return current_value __js_engine: JSEngine = NodeJSEngine() def get_js_engine() -> JSEngine: return __js_engine def set_js_engine(js_engine: JSEngine) -> None: global __js_engine __js_engine = js_engine # The following functions are maintained for compatibility purposes def check_js_threshold_version(*args: Any, **kwargs: Any) -> bool: _check_js_threshold_version = getattr( get_js_engine(), "check_js_threshold_version", None ) if callable(_check_js_threshold_version): return cast(bool, _check_js_threshold_version(*args, **kwargs)) else: raise NotImplementedError( "Method check_js_threshold_version is not implemented in js engine {}".format( get_js_engine().__class__.__name__ ) ) def exec_js_process(*args: Any, **kwargs: Any) -> tuple[int, str, str]: """ Run a javascript text. :param timeout: Max number of seconds to wait. :returns: A tuple of the return code, stdout, and stderr of the javascript engine invocation. """ _exec_js_process = getattr(get_js_engine(), "exec_js_process", None) if callable(_exec_js_process): return cast(tuple[int, str, str], _exec_js_process(*args, **kwargs)) else: raise NotImplementedError( "Method exec_js_process is not implemented in js engine {}".format( get_js_engine().__class__.__name__ ) ) def new_js_proc(*args: Any, **kwargs: Any) -> "subprocess.Popen[str]": _new_js_proc = getattr(get_js_engine(), "new_js_proc", None) if callable(_new_js_proc): return cast("subprocess.Popen[str]", _new_js_proc(*args, **kwargs)) else: raise NotImplementedError( "Method new_js_proc is not implemented in js engine {}".format( get_js_engine().__class__.__name__ ) ) cwl_utils-0.41/cwl_utils/schemadef.py0000644000000000000000000002023213615410400014660 0ustar00# SPDX-License-Identifier: Apache-2.0 # Copyright (c) 2023 Genomics plc # Copyright (c) 2021 Michael R. Crusoe # Copyright (c) 2020 Seven Bridges # See https://github.com/rabix/sbpack/blob/b8404a0859ffcbe1edae6d8f934e51847b003320/LICENSE """ Valid forms of user defined types stored in external file. A single dictionary (tests/types/singletype.yml) A list of dictionaries (e.g. tests/types/recursive.yml) Types can refer to other types in the file Names can not clash across files (This seems arbitrary and we allow that for packing) Only records and arrays can be defined (https://github.com/common-workflow-language/cwl-v1.2/pull/14) From https://github.com/rabix/sbpack/blob/b8404a0859ffcbe1edae6d8f934e51847b003320/sbpack/lib.py """ import sys import urllib.parse from copy import deepcopy from typing import Any, cast from cwl_utils import errors, types, utils def build_user_defined_type_dict( cwl: dict[str, Any], base_url: urllib.parse.ParseResult ) -> dict[str, Any]: user_defined_types = {} # Check for `$import` directly under `requirements` so we can specially handle # the new base_url for index, entry in enumerate(cwl.get("requirements", [])): if isinstance(entry, dict) and "$import" in entry: requirement, new_base_url = utils.load_linked_file( base_url, entry["$import"], is_import=True ) if requirement["class"] == "SchemaDefRequirement": cwl["requirements"][index] = requirement type_definition_list = requirement["types"] path_prefix = new_base_url.geturl() sys.stderr.write( f"Parsing {len(type_definition_list)} types from {path_prefix}\n" ) for v in type_definition_list: k = v.get("name") if k is None: raise RuntimeError(f"In file {path_prefix} type missing name") user_defined_types[f"{path_prefix}#{k}"] = v return _build_user_defined_type_dict(cwl, base_url, user_defined_types) def _build_user_defined_type_dict( cwl: dict[str, Any], base_url: urllib.parse.ParseResult, user_defined_types: dict[str, Any], ) -> dict[str, Any]: schemadef: dict[str, str] = next( ( req for req in cwl.get("requirements", []) if req.get("class") == "SchemaDefRequirement" ), {}, ) schema_list = cast(list[dict[str, Any]], schemadef.get("types", [])) if not isinstance(schema_list, list): raise RuntimeError( f"In file {base_url.geturl()}: " f"Schemadef types have to be a list\n" f"Instead, got: {schema_list}" ) for schema in schema_list: if not isinstance(schema, dict): raise RuntimeError( f"In file {base_url.geturl()}: " f"User type has to be a dict\n" f"Instead, got: {schema}" ) if len(schema.keys()) == 1 and list(schema.keys())[0] == "$import": type_definition_list, this_url = utils.load_linked_file( base_url, schema["$import"], is_import=True ) # This is always a list if isinstance(type_definition_list, dict): type_definition_list = [type_definition_list] # except when it isn't path_prefix = ( this_url.geturl() ) # sbpack.lib.normalized_path(schema["$import"], base_url).geturl() sys.stderr.write( f"Parsing {len(type_definition_list)} types from {path_prefix}\n" ) for v in type_definition_list: k = v.get("name") if k is None: raise RuntimeError(f"In file {path_prefix} type missing name") user_defined_types[f"{path_prefix}#{k}"] = v else: path_prefix = base_url.geturl() user_defined_types[f"{path_prefix}#{schema.get('name')}"] = schema # sys.stderr.write(str(user_defined_types)) # sys.stderr.write("\n") return user_defined_types # port = "input" or "output" def inline_types( cwl: dict[str, Any], port: str, base_url: urllib.parse.ParseResult, user_defined_types: dict[str, Any], ) -> dict[str, Any]: if ( len(cwl[port]) == 1 and isinstance(cwl[port][0], dict) and cwl[port][0]["id"] == "$import" ): defs, base_url = utils.load_linked_file( base_url, cwl[port][0]["type"], is_import=True ) else: defs = cwl[port] cwl[port] = [_inline_type(v, base_url, user_defined_types) for v in defs] return cwl _inline_type_name_uniq_id = 0 _inline_type_names: set[str] = set() def _inline_type( v: Any, base_url: urllib.parse.ParseResult, user_defined_types: dict[str, Any] ) -> Any: global _inline_type_name_uniq_id _inline_type_name_uniq_id += 1 if isinstance(v, str): # Handle syntactic sugar if v.endswith("[]"): return { "type": "array", "items": _inline_type(v[:-2], base_url, user_defined_types), } if v.endswith("?"): return ["null", _inline_type(v[:-1], base_url, user_defined_types)] if v in types.built_in_types: return v if "#" not in v: path_prefix = base_url path_suffix = v else: parts = v.split("#") path_prefix = utils.resolved_path(base_url, parts[0]) path_suffix = parts[1] path = f"{path_prefix.geturl()}#{path_suffix}" if path not in user_defined_types: raise RuntimeError( f"Could not find type {path!r} in {user_defined_types!r}." ) else: resolve_type = deepcopy(user_defined_types[path]) # resolve_type.pop("name", None) # Should work, but cwltool complains if "name" in resolve_type: user_type_name = resolve_type["name"] if user_type_name in _inline_type_names: resolve_type["name"] = ( f"{user_type_name}_{_inline_type_name_uniq_id}" ) else: _inline_type_names.add(user_type_name) else: resolve_type["name"] = f"user_type_{_inline_type_name_uniq_id}" return _inline_type(resolve_type, path_prefix, user_defined_types) elif isinstance(v, list): return [_inline_type(_v, base_url, user_defined_types) for _v in v] elif isinstance(v, dict): if v.get("$import") is not None: imported_type, import_base_url = utils.load_linked_file( base_url, v["$import"], is_import=True ) return _inline_type(imported_type, import_base_url, user_defined_types) _type = v.get("type") if _type is None: raise errors.MissingTypeName( f"In file {base_url.geturl()}, type {v.get('name')} is missing type name" ) elif _type == "enum": return v elif _type == "array": if "items" not in v: raise errors.ArrayMissingItems( f"In file {base_url.geturl()}, array type {_type.get('name')} is missing 'items'" ) v["items"] = _inline_type(v["items"], base_url, user_defined_types) return v elif _type == "record": if "fields" not in v: raise errors.RecordMissingFields( f"In file {base_url.geturl()}, record type {_type.get('name')} is missing 'fields'" ) fields = utils.normalize_to_list( v["fields"], key_field="name", value_field="type" ) v["fields"] = [ _inline_type(_f, base_url, user_defined_types) for _f in fields ] return v elif _type in types.built_in_types: return v else: v["type"] = _inline_type(_type, base_url, user_defined_types) return v else: raise RuntimeError("Found a type sbpack can not understand") cwl_utils-0.41/cwl_utils/singularity.py0000644000000000000000000000622113615410400015315 0ustar00"""Support Singularity{,-CE} {2,3}.x or Apptainer 1.x.""" import re from subprocess import check_output # nosec from .loghandler import _logger # Cached version number of singularity # This is a list containing major and minor versions as integer. # (The number of minor version digits can vary among different distributions, # therefore we need a list here.) _SINGULARITY_VERSION: list[int] | None = None # Cached flavor / distribution of singularity # Can be singularity, singularity-ce or apptainer _SINGULARITY_FLAVOR: str = "" def get_version() -> tuple[list[int], str]: """ Parse the output of 'singularity --version' to determine the flavor and version. Both pieces of information will be cached. :returns: A tuple containing: - A tuple with major and minor version numbers as integer. - A string with the name of the singularity flavor. """ global _SINGULARITY_VERSION, _SINGULARITY_FLAVOR # pylint: disable=global-statement if _SINGULARITY_VERSION is None: version_output = check_output( # nosec ["singularity", "--version"], text=True ).strip() version_match = re.match(r"(.+) version ([0-9\.]+)", version_output) if version_match is None: raise RuntimeError("Output of 'singularity --version' not recognized.") version_string = version_match.group(2) _SINGULARITY_VERSION = [int(i) for i in version_string.split(".")] _SINGULARITY_FLAVOR = version_match.group(1) _logger.debug( f"Singularity version: {version_string}" " ({_SINGULARITY_FLAVOR}." ) return (_SINGULARITY_VERSION, _SINGULARITY_FLAVOR) def is_apptainer_1_or_newer() -> bool: """ Check if apptainer singularity distribution is version 1.0 or higher. Apptainer v1.0.0 is compatible with SingularityCE 3.9.5. See: https://github.com/apptainer/apptainer/releases """ v = get_version() if v[1] != "apptainer": return False return v[0][0] >= 1 def is_version_2_6() -> bool: """ Check if this singularity version is exactly version 2.6. Also returns False if the flavor is not singularity or singularity-ce. """ v = get_version() if v[1] != "singularity" and v[1] != "singularity-ce": return False return v[0][0] == 2 and v[0][1] == 6 def is_version_3_or_newer() -> bool: """Check if this version is singularity version 3 or newer or equivalent.""" if is_apptainer_1_or_newer(): return True # this is equivalent to singularity-ce > 3.9.5 v = get_version() return v[0][0] >= 3 def is_version_3_1_or_newer() -> bool: """Check if this version is singularity version 3.1 or newer or equivalent.""" if is_apptainer_1_or_newer(): return True # this is equivalent to singularity-ce > 3.9.5 v = get_version() return v[0][0] >= 4 or (v[0][0] == 3 and v[0][1] >= 1) def is_version_3_4_or_newer() -> bool: """Detect if Singularity v3.4+ is available.""" if is_apptainer_1_or_newer(): return True # this is equivalent to singularity-ce > 3.9.5 v = get_version() return v[0][0] >= 4 or (v[0][0] == 3 and v[0][1] >= 4) cwl_utils-0.41/cwl_utils/types.py0000644000000000000000000000705413615410400014114 0ustar00# SPDX-License-Identifier: Apache-2.0 # From https://github.com/rabix/sbpack/blob/b8404a0859ffcbe1edae6d8f934e51847b003320/sbpack/lib.py """Shared Python type definitions for commons JSON like CWL objects.""" import sys from collections.abc import Mapping, MutableMapping, MutableSequence from typing import Any, Literal, TypeAlias, TypedDict, TypeGuard if sys.version_info >= (3, 13): from typing import TypeIs else: from typing_extensions import TypeIs if sys.version_info >= (3, 11): from typing import Required else: from typing_extensions import Required built_in_types: list[str] = [ "null", "boolean", "int", "long", "float", "double", "string", "File", "Directory", "stdin", "stdout", "stderr", "Any", ] CWLDirectoryType = TypedDict( "CWLDirectoryType", { "class": Required[Literal["Directory"]], "location": str, "path": str, "basename": str, "listing": MutableSequence["CWLFileType | CWLDirectoryType"], }, total=False, ) CWLFileType = TypedDict( "CWLFileType", { "class": Required[Literal["File"]], "location": str, "path": str, "basename": str, "dirname": str, "nameroot": str, "nameext": str, "checksum": str, "size": int, "secondaryFiles": MutableSequence["CWLFileType | CWLDirectoryType"], "format": str, "contents": str, }, total=False, ) CWLOutputType: TypeAlias = ( bool | str | int | float | CWLFileType | CWLDirectoryType | MutableSequence["CWLOutputType | None"] | MutableMapping[str, "CWLOutputType | None"] ) CWLObjectType: TypeAlias = MutableMapping[str, CWLOutputType | None] SinkType: TypeAlias = CWLOutputType | CWLObjectType class CWLRuntimeParameterContext(TypedDict, total=False): outdir: str tmpdir: str cores: float | str ram: float | str outdirSize: float | str tmpdirSize: float | str exitCode: int class CWLParameterContext(TypedDict, total=False): inputs: CWLObjectType self: CWLOutputType | None runtime: CWLRuntimeParameterContext class DirentType(TypedDict, total=False): entry: Required[str] entryname: str writable: bool def is_cwl_parameter_context_key( key: Any, ) -> TypeGuard[Literal["inputs", "self", "runtime"]]: return key in ("inputs", "self", "runtime") def is_directory(value: Any) -> TypeIs[CWLDirectoryType]: return isinstance(value, Mapping) and value.get("class") == "Directory" def is_directory_key( key: Any, ) -> TypeGuard[Literal["class", "location", "path", "basename", "listing"]]: return key in ("class", "location", "path", "basename", "listing") def is_file(value: Any) -> TypeIs[CWLFileType]: return isinstance(value, Mapping) and value.get("class") == "File" def is_file_key( key: Any, ) -> TypeGuard[ Literal[ "class", "location", "path", "basename", "dirname", "nameroot", "nameext", "checksum", "size", "secondaryFiles", "format", "contents", ] ]: return key in ( "class", "location", "path", "basename", "dirname", "nameroot", "nameext", "checksum", "size", "secondaryFiles", "format", "contents", ) def is_file_or_directory( value: Any, ) -> TypeIs[CWLFileType | CWLDirectoryType]: return isinstance(value, Mapping) and value.get("class") in ("File", "Directory") cwl_utils-0.41/cwl_utils/utils.py0000644000000000000000000003123313615410400014104 0ustar00# SPDX-License-Identifier: Apache-2.0 """Miscellaneous utility functions.""" import pathlib import subprocess # nosec import sys import urllib.error import urllib.parse import urllib.request from collections.abc import MutableMapping, MutableSequence from copy import deepcopy from importlib.resources import files from io import StringIO from typing import Any from urllib.parse import urlparse from ruamel.yaml.main import YAML from ruamel.yaml.parser import ParserError from ruamel.yaml.scanner import ScannerError from cwl_utils.errors import MissingKeyField from cwl_utils.loghandler import _logger # Type hinting from cwl_utils.parser import cwl_v1_0, cwl_v1_1, cwl_v1_2 # Load as 1.2 files from cwl_utils.parser.cwl_v1_2 import InputArraySchema as InputArraySchemaV1_2 from cwl_utils.parser.cwl_v1_2 import InputEnumSchema as InputEnumSchemaV1_2 fast_yaml = YAML(typ="safe") _USERNS: bool | None = None def _is_github_symbolic_link(base_url: urllib.parse.ParseResult, contents: str) -> bool: """ Test if link is a GitHub style symbolic link. Look for remote path with contents that is a single line with no new line with an extension. https://github.com/rabix/sbpack/blob/b8404a0859ffcbe1edae6d8f934e51847b003320/sbpack/lib.py """ if base_url.scheme in ("file://", ""): return False idx = contents.find("\n") if idx > -1: return False if "." not in contents: return False return True def bytes2str_in_dicts( inp: MutableMapping[str, Any] | MutableSequence[Any] | Any, ) -> str | MutableSequence[Any] | MutableMapping[str, Any]: """ Convert any present byte string to unicode string, inplace. input is a dict of nested dicts and lists """ # if input is dict, recursively call for each value if isinstance(inp, MutableMapping): for k in inp: inp[k] = bytes2str_in_dicts(inp[k]) return inp # if list, iterate through list and fn call # for all its elements if isinstance(inp, MutableSequence): for idx, value in enumerate(inp): inp[idx] = bytes2str_in_dicts(value) return inp # if value is bytes, return decoded string, elif isinstance(inp, bytes): return inp.decode("utf-8") # simply return elements itself return inp def load_linked_file( base_url: urllib.parse.ParseResult, link: str, is_import: bool = False ) -> tuple[Any, urllib.parse.ParseResult]: """From https://github.com/rabix/sbpack/blob/b8404a0859ffcbe1edae6d8f934e51847b003320/sbpack/lib.py .""" new_url = resolved_path(base_url, link) if new_url.scheme in ("file://", ""): contents = pathlib.Path(new_url.path).read_text() else: try: contents = ( urllib.request.urlopen(new_url.geturl()).read().decode("utf-8") # nosec ) except urllib.error.HTTPError as e: _logger.error("Could not find linked file: %s", new_url.geturl()) raise SystemExit(e) from e if _is_github_symbolic_link(new_url, contents): # This is an exception for symbolic links on github sys.stderr.write( f"{new_url.geturl()}: found file-like string in contents.\n" f"Treating as github symbolic link to {contents}\n" ) return load_linked_file(new_url, contents, is_import=is_import) if is_import: try: _node = fast_yaml.load(contents) except ParserError as e: e.context = f"\n===\nMalformed file: {new_url.geturl()}\n===\n" + e.context raise SystemExit(e) from e except ScannerError as e: e.problem = f"\n===\nMalformed file: {new_url.geturl()}\n===\n" + e.problem raise SystemExit(e) from e else: _node = contents return _node, new_url def normalize_to_map(obj: list[Any] | dict[str, Any], key_field: str) -> dict[str, Any]: """From https://github.com/rabix/sbpack/blob/b8404a0859ffcbe1edae6d8f934e51847b003320/sbpack/lib.py .""" if isinstance(obj, dict): return deepcopy(obj) elif isinstance(obj, list): map_obj = {} for v in obj: if not isinstance(v, dict): raise RuntimeError("Expecting a dict here") k = v.get(key_field) if k is None: raise MissingKeyField(key_field) v.pop(key_field, None) map_obj[k] = v return map_obj else: raise RuntimeError("Expecting a dictionary or a list here") def normalize_to_list( obj: list[Any] | dict[str, Any], key_field: str, value_field: str | None ) -> list[Any]: """From https://github.com/rabix/sbpack/blob/b8404a0859ffcbe1edae6d8f934e51847b003320/sbpack/lib.py .""" if isinstance(obj, list): return deepcopy(obj) elif isinstance(obj, dict): map_list = [] for k, v in obj.items(): if not isinstance(v, dict): if value_field is None: raise RuntimeError(f"Expecting a dict here, got {v}") v = {value_field: v} v.update({key_field: k}) map_list += [v] return map_list else: raise RuntimeError("Expecting a dictionary or a list here") def resolved_path( base_url: urllib.parse.ParseResult, link: str ) -> urllib.parse.ParseResult: """ Derive a resolved path. This function will 1. Resolve the path, which means dot and double dot components are resolved 2. Use the OS appropriate path resolution for local paths, and network appropriate resolution for network paths From https://github.com/rabix/sbpack/blob/b8404a0859ffcbe1edae6d8f934e51847b003320/sbpack/lib.py :param base_url: "this document" :param link: "string in this document" :returns: new URL that allows us to retrieve the linked document """ link_url = urllib.parse.urlparse(link) # The link will always Posix if link_url.scheme == "file://": # Absolute local path return link_url elif link_url.scheme == "": # Relative path, can be local or remote if base_url.scheme in ("file://", ""): # Local relative path if link == "": return base_url else: return urllib.parse.urlparse( urllib.parse.urljoin(base_url.geturl(), link_url.geturl()) ) else: # Remote relative path return urllib.parse.urlparse( urllib.parse.urljoin(base_url.geturl(), link_url.path) ) # We need urljoin because we need to resolve relative links in a # platform independent manner # Absolute remote path return link_url def singularity_supports_userns() -> bool: """Confirm if the version of Singularity install supports the --userns flag.""" global _USERNS # pylint: disable=global-statement if _USERNS is None: try: hello_image = files("cwl_utils").joinpath("hello.simg") result = subprocess.Popen( # nosec ["singularity", "exec", "--userns", str(hello_image), "true"], stderr=subprocess.PIPE, stdout=subprocess.DEVNULL, universal_newlines=True, ).communicate(timeout=60)[1] _USERNS = ( "No valid /bin/sh" in result or "/bin/sh doesn't exist in container" in result or "executable file not found in" in result ) except subprocess.TimeoutExpired: _USERNS = False return _USERNS def yaml_dumps(obj: Any) -> str: """ Shortcut. Don't use if you have a file descriptor (like sys.stdout) available. """ yaml = YAML() stream = StringIO() yaml.dump(obj, stream) return stream.getvalue() def to_pascal_case(name: str) -> str: """ Convert a string to PascalCase. fastq-list-row to FastqListRow fastq_list_row to FastqListRow :param name: :return: """ return "".join(map(str.capitalize, name.replace("_", "-").split("-"))) def sanitise_schema_field( schema_field_item: dict[str, Any] | str, ) -> dict[str, Any] | str: """ Schemas need to be resolved before converted to JSON properties. Convert { 'type': 'Directory?' } To { 'type': ['null', 'Directory'] } Convert { 'type': 'string[]' } To InputArraySchema( type_=array, items=string ) Convert { 'type': 'File[]?' } To { 'type': [ 'null', InputArraySchema( type_=array, items=File ) ] } Convert { 'type': 'Enum', 'symbols': ['A', 'B', 'C'] } To { 'type': InputEnumSchema( type_=enum, symbols=['A', 'B', 'C'] ) } Convert { 'type': 'array', 'items': { '$import': '../../../schemas/fastq-list-row/1.0.0/fastq-list-row__1.0.0.yaml#fastq-list-row' } } To { 'type': InputArraySchema( type_=array, items={ '$import': '../../../schemas/fastq-list-row/1.0.0/fastq-list-row__1.0.0.yaml#fastq-list-row' } ) } :param schema_field_item: :return: """ # We might be just a string, in which case, just return # This happens in the case that type is a list of primitive types if isinstance(schema_field_item, str): return schema_field_item # Copy schema field schema_field_item = deepcopy(schema_field_item) required = True match schema_field_item: case ( cwl_v1_0.InputRecordSchema() | cwl_v1_1.InputRecordSchema() | cwl_v1_2.InputRecordSchema() ): return schema_field_item case {"type": list(field_item_type)}: if "null" in field_item_type: required = False schema_field_item["type"] = list( filter(lambda type_item: type_item != "null", field_item_type) ) if len(schema_field_item["type"]) == 1: schema_field_item["type"] = schema_field_item["type"][0] else: # Recursively get items schema_field_item["type"] = list( map( sanitise_schema_field, schema_field_item.get("type", []), ) ) case {"type": str(field_item_type)}: if field_item_type.endswith("?"): required = False schema_field_item["type"] = schema_field_item.get("type", "").replace( "?", "" ) if schema_field_item.get("type", "").endswith("[]"): # Strip list schema_field_item["type"] = schema_field_item.get("type", "").replace( "[]", "" ) # Convert to array schema_field_item["type"] = InputArraySchemaV1_2( type_="array", items=schema_field_item.get("type", "") ) case {"type": {"type": "enum", **rest}}: schema_field_item["type"] = InputEnumSchemaV1_2( type_="enum", symbols=rest.get("symbols", ""), ) case {"type": {"type": "array", **rest}}: schema_field_item["type"] = InputArraySchemaV1_2( type_="array", items=rest.get("items", "") ) case {"type": {"$import": _}}: pass # Leave import as is case {"type": dict()}: raise ValueError(f"Unknown type: {schema_field_item.get('type')}") if not required: if isinstance(schema_field_item.get("type"), list): schema_field_item["type"] = ["null"] + schema_field_item.get("type", []) else: schema_field_item["type"] = ["null", schema_field_item.get("type", "")] return schema_field_item def is_uri(uri: str) -> bool: """ Given a URI return True if it is a URI. :param uri: :return: """ if not urlparse(uri).scheme == "": return True return False def is_local_uri(uri: str) -> bool: """Given a uri, first check if it is a uri, then check if it is a local uri.""" if is_uri(uri) and urlparse(uri).scheme == "file": return True return False def get_value_from_uri(uri: str) -> str: """ Given a URI, return the value after #. file://path/to/imported/record#my_workflow_name/record_name Returns record_name :param uri: :return: """ url_obj = urlparse(uri) return url_obj.fragment.rsplit("/")[-1] cwl_utils-0.41/cwl_utils/parser/__init__.py0000644000000000000000000003727413615410400016012 0ustar00# SPDX-License-Identifier: Apache-2.0 import os from abc import ABC from collections.abc import MutableMapping, MutableSequence from pathlib import Path from typing import Any, Optional, TypeAlias, cast from urllib.parse import unquote_plus, urlparse from schema_salad.exceptions import ValidationException from schema_salad.utils import yaml_no_ts from ..errors import GraphTargetMissingException from . import cwl_v1_0, cwl_v1_1, cwl_v1_2 class NoType(ABC): pass LoadingOptions: TypeAlias = ( cwl_v1_0.LoadingOptions | cwl_v1_1.LoadingOptions | cwl_v1_2.LoadingOptions ) """Type union for a CWL v1.x LoadingOptions object.""" Saveable: TypeAlias = cwl_v1_0.Saveable | cwl_v1_1.Saveable | cwl_v1_2.Saveable """Type union for a CWL v1.x Saveable object.""" InputParameter: TypeAlias = ( cwl_v1_0.InputParameter | cwl_v1_1.InputParameter | cwl_v1_2.InputParameter ) """Type union for a CWL v1.x InputEnumSchema object.""" InputRecordField: TypeAlias = ( cwl_v1_0.InputRecordField | cwl_v1_1.InputRecordField | cwl_v1_2.InputRecordField ) """Type union for a CWL v1.x InputRecordSchema object.""" InputSchema: TypeAlias = ( cwl_v1_0.InputSchema | cwl_v1_1.InputSchema | cwl_v1_2.InputSchema ) """Type union for a CWL v1.x InputSchema object.""" OutputParameter: TypeAlias = ( cwl_v1_0.OutputParameter | cwl_v1_1.OutputParameter | cwl_v1_2.OutputParameter ) """Type union for a CWL v1.x OutputParameter object.""" OutputArraySchema: TypeAlias = ( cwl_v1_0.OutputArraySchema | cwl_v1_1.OutputArraySchema | cwl_v1_2.OutputArraySchema ) """Type union for a CWL v1.x OutputArraySchema object.""" OutputEnumSchema: TypeAlias = ( cwl_v1_0.OutputEnumSchema | cwl_v1_1.OutputEnumSchema | cwl_v1_2.OutputEnumSchema ) """Type union for a CWL v1.x OutputEnumSchema object.""" OutputRecordField: TypeAlias = ( cwl_v1_0.OutputRecordField | cwl_v1_1.OutputRecordField | cwl_v1_2.OutputRecordField ) """Type union for a CWL v1.x OutputRecordField object.""" OutputRecordSchema: TypeAlias = ( cwl_v1_0.OutputRecordSchema | cwl_v1_1.OutputRecordSchema | cwl_v1_2.OutputRecordSchema ) """Type union for a CWL v1.x OutputRecordSchema object.""" OutputSchema: TypeAlias = ( cwl_v1_0.OutputSchema | cwl_v1_1.OutputSchema | cwl_v1_2.OutputSchema ) """Type union for a CWL v1.x OutputSchema object.""" Workflow: TypeAlias = cwl_v1_0.Workflow | cwl_v1_1.Workflow | cwl_v1_2.Workflow WorkflowTypes = (cwl_v1_0.Workflow, cwl_v1_1.Workflow, cwl_v1_2.Workflow) """Type union for a CWL v1.x Workflow object.""" WorkflowInputParameter: TypeAlias = ( cwl_v1_0.InputParameter | cwl_v1_1.WorkflowInputParameter | cwl_v1_2.WorkflowInputParameter ) """Type union for a CWL v1.x WorkflowInputParameter object.""" WorkflowOutputParameter: TypeAlias = ( cwl_v1_0.WorkflowOutputParameter | cwl_v1_1.WorkflowOutputParameter | cwl_v1_2.WorkflowOutputParameter ) """Type union for a CWL v1.x WorkflowOutputParameter object.""" WorkflowStep: TypeAlias = ( cwl_v1_0.WorkflowStep | cwl_v1_1.WorkflowStep | cwl_v1_2.WorkflowStep ) """Type union for a CWL v1.x WorkflowStep object.""" ScatterWorkflowStep: TypeAlias = ( cwl_v1_0.WorkflowStep | cwl_v1_1.WorkflowStep | cwl_v1_2.WorkflowStep ) """Type union for a CWL v1.x ScatterWorkflowStep object.""" LoopWorkflowStep: TypeAlias = NoType """Type union for a CWL v1.x LoopWorkflowStep object.""" WorkflowStepInput: TypeAlias = ( cwl_v1_0.WorkflowStepInput | cwl_v1_1.WorkflowStepInput | cwl_v1_2.WorkflowStepInput ) """Type union for a CWL v1.x WorkflowStepInput object.""" WorkflowStepOutput: TypeAlias = ( cwl_v1_0.WorkflowStepOutput | cwl_v1_1.WorkflowStepOutput | cwl_v1_2.WorkflowStepOutput ) """Type union for a CWL v1.x WorkflowStepOutput object.""" CommandLineTool: TypeAlias = ( cwl_v1_0.CommandLineTool | cwl_v1_1.CommandLineTool | cwl_v1_2.CommandLineTool ) CommandLineToolTypes = ( cwl_v1_0.CommandLineTool, cwl_v1_1.CommandLineTool, cwl_v1_2.CommandLineTool, ) """Type union for a CWL v1.x CommandLineTool object.""" CommandLineBinding: TypeAlias = ( cwl_v1_0.CommandLineBinding | cwl_v1_1.CommandLineBinding | cwl_v1_2.CommandLineBinding ) """Type union for a CWL v1.x CommandLineBinding object.""" CommandOutputBinding: TypeAlias = ( cwl_v1_0.CommandOutputBinding | cwl_v1_1.CommandOutputBinding | cwl_v1_2.CommandOutputBinding ) """Type union for a CWL v1.x CommandOutputBinding object.""" CommandInputParameter: TypeAlias = ( cwl_v1_0.CommandInputParameter | cwl_v1_1.CommandInputParameter | cwl_v1_2.CommandInputParameter ) """Type union for a CWL v1.x CommandInputParameter object.""" CommandOutputParameter: TypeAlias = ( cwl_v1_0.CommandOutputParameter | cwl_v1_1.CommandOutputParameter | cwl_v1_2.CommandOutputParameter ) """Type union for a CWL v1.x CommandOutputParameter object.""" CommandOutputRecordField: TypeAlias = ( cwl_v1_0.CommandOutputRecordField | cwl_v1_1.CommandOutputRecordField | cwl_v1_2.CommandOutputRecordField ) """Type union for a CWL v1.x CommandOutputRecordField object.""" ExpressionTool: TypeAlias = ( cwl_v1_0.ExpressionTool | cwl_v1_1.ExpressionTool | cwl_v1_2.ExpressionTool ) """Type union for a CWL v1.x ExpressionTool object.""" ExpressionToolOutputParameter: TypeAlias = ( cwl_v1_0.ExpressionToolOutputParameter | cwl_v1_1.ExpressionToolOutputParameter | cwl_v1_2.ExpressionToolOutputParameter ) """Type union for a CWL v1.x ExpressionToolOutputParameter object.""" DockerRequirement: TypeAlias = ( cwl_v1_0.DockerRequirement | cwl_v1_1.DockerRequirement | cwl_v1_2.DockerRequirement ) DockerRequirementTypes = ( cwl_v1_0.DockerRequirement, cwl_v1_1.DockerRequirement, cwl_v1_2.DockerRequirement, ) """Type union for a CWL v1.x DockerRequirement object.""" Process: TypeAlias = Workflow | CommandLineTool | ExpressionTool | cwl_v1_2.Operation """Type Union for a CWL v1.x Process object.""" ProcessRequirement: TypeAlias = ( cwl_v1_0.ProcessRequirement | cwl_v1_1.ProcessRequirement | cwl_v1_2.ProcessRequirement ) """Type Union for a CWL v1.x ProcessRequirement object.""" ProcessRequirementTypes = ( cwl_v1_0.ProcessRequirement, cwl_v1_1.ProcessRequirement, cwl_v1_2.ProcessRequirement, ) SoftwareRequirement: TypeAlias = ( cwl_v1_0.SoftwareRequirement | cwl_v1_1.SoftwareRequirement | cwl_v1_2.SoftwareRequirement ) SoftwareRequirementTypes = ( cwl_v1_0.SoftwareRequirement, cwl_v1_1.SoftwareRequirement, cwl_v1_2.SoftwareRequirement, ) """Type union for a CWL v1.x SoftwareRequirement object.""" ArraySchema: TypeAlias = ( cwl_v1_0.ArraySchema | cwl_v1_1.ArraySchema | cwl_v1_2.ArraySchema ) InputArraySchema: TypeAlias = ( cwl_v1_0.InputArraySchema | cwl_v1_1.InputArraySchema | cwl_v1_2.InputArraySchema ) InputArraySchemaTypes = ( cwl_v1_0.InputArraySchema, cwl_v1_1.InputArraySchema, cwl_v1_2.InputArraySchema, ) """Type Union for a CWL v1.x ArraySchema object.""" EnumSchema: TypeAlias = cwl_v1_0.EnumSchema | cwl_v1_1.EnumSchema | cwl_v1_2.EnumSchema InputEnumSchema: TypeAlias = ( cwl_v1_0.InputEnumSchema | cwl_v1_1.InputEnumSchema | cwl_v1_2.InputEnumSchema ) InputEnumSchemaTypes = ( cwl_v1_0.InputEnumSchema, cwl_v1_1.InputEnumSchema, cwl_v1_2.InputEnumSchema, ) """Type Union for a CWL v1.x EnumSchema object.""" RecordSchema: TypeAlias = ( cwl_v1_0.RecordSchema | cwl_v1_1.RecordSchema | cwl_v1_2.RecordSchema ) InputRecordSchema: TypeAlias = ( cwl_v1_0.InputRecordSchema | cwl_v1_1.InputRecordSchema | cwl_v1_2.InputRecordSchema ) InputRecordSchemaTypes = ( cwl_v1_0.InputRecordSchema, cwl_v1_1.InputRecordSchema, cwl_v1_2.InputRecordSchema, ) """Type Union for a CWL v1.x RecordSchema object.""" File: TypeAlias = cwl_v1_0.File | cwl_v1_1.File | cwl_v1_2.File """Type Union for a CWL v1.x File object.""" SecondaryFileSchema: TypeAlias = ( cwl_v1_1.SecondaryFileSchema | cwl_v1_2.SecondaryFileSchema ) """Type Union for a CWL v1.x SecondaryFileSchema object.""" Directory: TypeAlias = cwl_v1_0.Directory | cwl_v1_1.Directory | cwl_v1_2.Directory """Type Union for a CWL v1.x Directory object.""" Dirent: TypeAlias = cwl_v1_0.Dirent | cwl_v1_1.Dirent | cwl_v1_2.Dirent """Type Union for a CWL v1.x Dirent object.""" LoadContents: TypeAlias = ( cwl_v1_1.CommandInputParameter | cwl_v1_2.CommandInputParameter | cwl_v1_1.CommandOutputBinding | cwl_v1_2.CommandOutputBinding | cwl_v1_1.InputRecordField | cwl_v1_2.InputRecordField | cwl_v1_1.WorkflowInputParameter | cwl_v1_2.WorkflowInputParameter | cwl_v1_1.WorkflowStepInput | cwl_v1_2.WorkflowStepInput ) """Type Union for a CWL v1.x LoadContents object.""" _Loader: TypeAlias = cwl_v1_0._Loader | cwl_v1_1._Loader | cwl_v1_2._Loader """Type union for a CWL v1.x _Loader.""" def _get_id_from_graph(yaml: MutableMapping[str, Any], id_: str | None) -> Any: if id_ is None: id_ = "main" for el in yaml["$graph"]: if el["id"].lstrip("#") == id_: return el raise GraphTargetMissingException( "Tool file contains graph of multiple objects, must specify " "one of #%s" % ", #".join(el["id"] for el in yaml["$graph"]) ) def cwl_version(yaml: Any) -> str | None: """ Return the cwlVersion of a YAML object. :param yaml: ruamel.yaml object for a CWL document :raises ValidationException: If `yaml` is not a MutableMapping. """ if not isinstance(yaml, MutableMapping): raise ValidationException("MutableMapping is required") if "cwlVersion" not in list(yaml.keys()): return None return cast(str, yaml["cwlVersion"]) def load_document_by_uri( path: str | Path, loadingOptions: LoadingOptions | None = None, load_all: bool = False, ) -> Any: """Load a CWL object from a URI or a path.""" if isinstance(path, str): uri = urlparse(path) id_ = uri.fragment or None if not uri.scheme or uri.scheme == "file": real_uri = Path(unquote_plus(uri.path)).resolve().as_uri() base_uri = Path(unquote_plus(uri.path)).resolve().parent.as_uri() else: real_uri = path base_uri = os.path.dirname(path) else: real_uri = path.resolve().as_uri() base_uri = path.resolve().parent.as_uri() id_ = path.resolve().name.split("#")[1] if "#" in path.resolve().name else None match loadingOptions: case cwl_v1_0.LoadingOptions(): loadingOptions = cwl_v1_0.LoadingOptions( fileuri=real_uri, baseuri=base_uri, copyfrom=loadingOptions ) return load_document_by_string( loadingOptions.fetcher.fetch_text(real_uri), real_uri, loadingOptions, id_, load_all, ) case cwl_v1_1.LoadingOptions(): loadingOptions = cwl_v1_1.LoadingOptions( fileuri=real_uri, baseuri=base_uri, copyfrom=loadingOptions ) return load_document_by_string( loadingOptions.fetcher.fetch_text(real_uri), real_uri, loadingOptions, id_, load_all, ) case cwl_v1_2.LoadingOptions(): loadingOptions = cwl_v1_2.LoadingOptions( fileuri=real_uri, baseuri=base_uri, copyfrom=loadingOptions ) return load_document_by_string( loadingOptions.fetcher.fetch_text(real_uri), real_uri, loadingOptions, id_, load_all, ) case None: loadingOptions = cwl_v1_2.LoadingOptions(fileuri=real_uri, baseuri=base_uri) return load_document_by_string( loadingOptions.fetcher.fetch_text(real_uri), real_uri, None, id_, load_all, ) case _: raise ValidationException( f"Unsupported loadingOptions type: {type(loadingOptions)}" ) def load_document( doc: Any, baseuri: str | None = None, loadingOptions: LoadingOptions | None = None, id_: str | None = None, load_all: bool = False, ) -> Any: """Load a CWL object from a serialized YAML string or a YAML object.""" if baseuri is None: baseuri = cwl_v1_0.file_uri(str(Path.cwd())) + "/" if isinstance(doc, str): return load_document_by_string(doc, baseuri, loadingOptions, id_) return load_document_by_yaml(doc, baseuri, loadingOptions, id_, load_all) def load_document_by_string( string: str, uri: str, loadingOptions: LoadingOptions | None = None, id_: str | None = None, load_all: bool = False, ) -> Any: """Load a CWL object from a serialized YAML string.""" result = yaml_no_ts().load(string) return load_document_by_yaml(result, uri, loadingOptions, id_, load_all) def load_document_by_yaml( yaml: Any, uri: str, loadingOptions: LoadingOptions | None = None, id_: str | None = None, load_all: bool = False, ) -> Any: """Load a CWL object from a YAML object.""" version = cwl_version(yaml) if "$graph" in yaml and not load_all: yaml = _get_id_from_graph(yaml, id_) yaml["cwlVersion"] = version match version: case "v1.0": result = cwl_v1_0.load_document_by_yaml( yaml, uri, cast(Optional[cwl_v1_0.LoadingOptions], loadingOptions) ) case "v1.1": result = cwl_v1_1.load_document_by_yaml( yaml, uri, cast(Optional[cwl_v1_1.LoadingOptions], loadingOptions) ) case "v1.2": result = cwl_v1_2.load_document_by_yaml( yaml, uri, cast(Optional[cwl_v1_2.LoadingOptions], loadingOptions) ) case None: raise ValidationException("could not get the cwlVersion") case _: raise ValidationException( f"Version error. Did not recognise {version} as a CWL version" ) if isinstance(result, MutableSequence): lst = [] for r in result: if "cwlVersion" in r.attrs: r.cwlVersion = version lst.append(r) return lst return result def save( val: Saveable | MutableSequence[Saveable] | None, top: bool = True, base_url: str = "", relative_uris: bool = True, ) -> Any: """Convert a CWL Python object into a JSON/YAML serializable object.""" match val: case cwl_v1_0.Saveable() | cwl_v1_1.Saveable() | cwl_v1_2.Saveable(): return val.save(top=top, base_url=base_url, relative_uris=relative_uris) case MutableSequence(): lst = [ save(v, top=top, base_url=base_url, relative_uris=relative_uris) for v in val ] if top and all(is_process(v) for v in val): vers = [ e.get("cwlVersion") for i, e in enumerate(lst) if is_process(val[i]) ] latest = max( (v for v in vers if v is not None), key=cast(Any, version_split) ) return {"cwlVersion": latest, "$graph": lst} return lst case MutableMapping(): newdict = {} for key in val: newdict[key] = save( val[key], top=False, base_url=base_url, relative_uris=relative_uris ) return newdict return val def is_process(v: Any) -> bool: """Test to see if the object is a CWL v1.x Python Process object.""" return isinstance(v, cwl_v1_0.Process | cwl_v1_1.Process | cwl_v1_2.Process) def version_split(version: str) -> MutableSequence[int]: """Split a cwlVersion value into its numerical components.""" return [int(v) for v in version[1:].split(".")] cwl_utils-0.41/cwl_utils/parser/cwl_v1_0.py0000644000000000000000000406270513615410400015666 0ustar00# # This file was autogenerated using schema-salad-tool --codegen=python # The code itself is released under the Apache 2.0 license and the help text is # subject to the license of the original schema. import copy import logging import os import pathlib import tempfile import uuid as _uuid__ # pylint: disable=unused-import # noqa: F401 import xml.sax # nosec from abc import ABC, abstractmethod from collections.abc import MutableMapping, MutableSequence, Sequence from io import StringIO from itertools import chain from typing import Any, Final, Optional, Union, cast from urllib.parse import quote, urldefrag, urlparse, urlsplit, urlunsplit from urllib.request import pathname2url from rdflib import Graph from rdflib.plugins.parsers.notation3 import BadSyntax from ruamel.yaml.comments import CommentedMap from schema_salad.exceptions import SchemaSaladException, ValidationException from schema_salad.fetcher import DefaultFetcher, Fetcher, MemoryCachingFetcher from schema_salad.sourceline import SourceLine, add_lc_filename from schema_salad.utils import CacheType, yaml_no_ts # requires schema-salad v8.2+ _vocab: dict[str, str] = {} _rvocab: dict[str, str] = {} _logger: Final = logging.getLogger("salad") IdxType = MutableMapping[str, tuple[Any, "LoadingOptions"]] class LoadingOptions: idx: Final[IdxType] fileuri: Final[Optional[str]] baseuri: Final[str] namespaces: Final[MutableMapping[str, str]] schemas: Final[MutableSequence[str]] original_doc: Final[Optional[Any]] addl_metadata: Final[MutableMapping[str, Any]] fetcher: Final[Fetcher] vocab: Final[dict[str, str]] rvocab: Final[dict[str, str]] cache: Final[CacheType] imports: Final[list[str]] includes: Final[list[str]] no_link_check: Final[Optional[bool]] container: Final[Optional[str]] def __init__( self, fetcher: Optional[Fetcher] = None, namespaces: Optional[dict[str, str]] = None, schemas: Optional[list[str]] = None, fileuri: Optional[str] = None, copyfrom: Optional["LoadingOptions"] = None, original_doc: Optional[Any] = None, addl_metadata: Optional[dict[str, str]] = None, baseuri: Optional[str] = None, idx: Optional[IdxType] = None, imports: Optional[list[str]] = None, includes: Optional[list[str]] = None, no_link_check: Optional[bool] = None, container: Optional[str] = None, ) -> None: """Create a LoadingOptions object.""" self.original_doc = original_doc if idx is not None: temp_idx = idx else: temp_idx = copyfrom.idx if copyfrom is not None else {} self.idx = temp_idx if fileuri is not None: temp_fileuri: Optional[str] = fileuri else: temp_fileuri = copyfrom.fileuri if copyfrom is not None else None self.fileuri = temp_fileuri if baseuri is not None: temp_baseuri = baseuri else: temp_baseuri = copyfrom.baseuri if copyfrom is not None else "" self.baseuri = temp_baseuri if namespaces is not None: temp_namespaces: MutableMapping[str, str] = namespaces else: temp_namespaces = copyfrom.namespaces if copyfrom is not None else {} self.namespaces = temp_namespaces if schemas is not None: temp_schemas: MutableSequence[str] = schemas else: temp_schemas = copyfrom.schemas if copyfrom is not None else [] self.schemas = temp_schemas if addl_metadata is not None: temp_addl_metadata: MutableMapping[str, Any] = addl_metadata else: temp_addl_metadata = copyfrom.addl_metadata if copyfrom is not None else {} self.addl_metadata = temp_addl_metadata if imports is not None: temp_imports = imports else: temp_imports = copyfrom.imports if copyfrom is not None else [] self.imports = temp_imports if includes is not None: temp_includes = includes else: temp_includes = copyfrom.includes if copyfrom is not None else [] self.includes = temp_includes if no_link_check is not None: temp_no_link_check: Optional[bool] = no_link_check else: temp_no_link_check = copyfrom.no_link_check if copyfrom is not None else False self.no_link_check = temp_no_link_check if container is not None: temp_container: Optional[str] = container else: temp_container = copyfrom.container if copyfrom is not None else None self.container = temp_container if fetcher is not None: temp_fetcher = fetcher elif copyfrom is not None: temp_fetcher = copyfrom.fetcher else: import requests from cachecontrol.caches import SeparateBodyFileCache from cachecontrol.wrapper import CacheControl root = pathlib.Path(os.environ.get("HOME", tempfile.gettempdir())) session = CacheControl( requests.Session(), cache=SeparateBodyFileCache(root / ".cache" / "salad"), ) temp_fetcher = DefaultFetcher({}, session) self.fetcher = temp_fetcher self.cache = self.fetcher.cache if isinstance(self.fetcher, MemoryCachingFetcher) else {} if self.namespaces != {}: temp_vocab = _vocab.copy() temp_rvocab = _rvocab.copy() for k, v in self.namespaces.items(): temp_vocab[k] = v temp_rvocab[v] = k else: temp_vocab = _vocab temp_rvocab = _rvocab self.vocab = temp_vocab self.rvocab = temp_rvocab @property def graph(self) -> Graph: """Generate a merged rdflib.Graph from all entries in self.schemas.""" graph = Graph() if not self.schemas: return graph key: Final = str(hash(tuple(self.schemas))) if key in self.cache: return cast(Graph, self.cache[key]) for schema in self.schemas: fetchurl = ( self.fetcher.urljoin(self.fileuri, schema) if self.fileuri is not None else pathlib.Path(schema).resolve().as_uri() ) if fetchurl not in self.cache or self.cache[fetchurl] is True: _logger.debug("Getting external schema %s", fetchurl) try: content = self.fetcher.fetch_text(fetchurl) except Exception as e: _logger.warning("Could not load extension schema %s: %s", fetchurl, str(e)) continue newGraph = Graph() err_msg = "unknown error" for fmt in ["xml", "turtle"]: try: newGraph.parse(data=content, format=fmt, publicID=str(fetchurl)) self.cache[fetchurl] = newGraph graph += newGraph break except (xml.sax.SAXParseException, TypeError, BadSyntax) as e: err_msg = str(e) else: _logger.warning("Could not load extension schema %s: %s", fetchurl, err_msg) self.cache[key] = graph return graph class Saveable(ABC): """Mark classes than have a save() and fromDoc() function.""" @classmethod @abstractmethod def fromDoc( cls, _doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None, ) -> "Saveable": """Construct this object from the result of yaml.load().""" @abstractmethod def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: """Convert this object to a JSON/YAML friendly dictionary.""" def load_field( val: Union[str, dict[str, str]], fieldtype: "_Loader", baseuri: str, loadingOptions: LoadingOptions, lc: Optional[list[Any]] = None, ) -> Any: """Load field.""" if isinstance(val, MutableMapping): if "$import" in val: if loadingOptions.fileuri is None: raise SchemaSaladException("Cannot load $import without fileuri") url1: Final = loadingOptions.fetcher.urljoin(loadingOptions.fileuri, val["$import"]) result, metadata = _document_load_by_url( fieldtype, url1, loadingOptions, ) loadingOptions.imports.append(url1) return result if "$include" in val: if loadingOptions.fileuri is None: raise SchemaSaladException("Cannot load $import without fileuri") url2: Final = loadingOptions.fetcher.urljoin(loadingOptions.fileuri, val["$include"]) val = loadingOptions.fetcher.fetch_text(url2) loadingOptions.includes.append(url2) return fieldtype.load(val, baseuri, loadingOptions, lc=lc) save_type = Optional[Union[MutableMapping[str, Any], MutableSequence[Any], int, float, bool, str]] def extract_type(val_type: type[Any]) -> str: """Take a type of value, and extracts the value as a string.""" val_str: Final = str(val_type) return val_str.split("'")[1] def convert_typing(val_type: str) -> str: """Normalize type names to schema-salad types.""" if "None" in val_type: return "null" if "CommentedSeq" in val_type or "list" in val_type: return "array" if "CommentedMap" in val_type or "dict" in val_type: return "object" if "False" in val_type or "True" in val_type: return "boolean" return val_type def parse_errors(error_message: str) -> tuple[str, str, str]: """Parse error messages from several loaders into one error message.""" if not error_message.startswith("Expected"): return error_message, "", "" vals: Final = error_message.split("\n") if len(vals) == 1: return error_message, "", "" types1: Final = set() for val in vals: individual_vals = val.split(" ") if val == "": continue if individual_vals[1] == "one": individual_vals = val.split("(")[1].split(",") for t in individual_vals: types1.add(t.strip(" ").strip(")\n")) elif individual_vals[2] == "").replace("'", "")) elif individual_vals[0] == "Value": types1.add(individual_vals[-1].strip(".")) else: types1.add(individual_vals[1].replace(",", "")) types2: Final = {val for val in types1 if val != "NoneType"} if "str" in types2: types3 = {convert_typing(val) for val in types2 if "'" not in val} else: types3 = types2 to_print = "" for val in types3: if "'" in val: to_print = "value" if len(types3) == 1 else "values" if to_print == "": to_print = "type" if len(types3) == 1 else "types" verb_tensage: Final = "is" if len(types3) == 1 else "are" return str(types3).replace("{", "(").replace("}", ")").replace("'", ""), to_print, verb_tensage def save( val: Any, top: bool = True, base_url: str = "", relative_uris: bool = True, ) -> save_type: if isinstance(val, Saveable): return val.save(top=top, base_url=base_url, relative_uris=relative_uris) if isinstance(val, MutableSequence): return [save(v, top=False, base_url=base_url, relative_uris=relative_uris) for v in val] if isinstance(val, MutableMapping): newdict: Final = {} for key in val: newdict[key] = save(val[key], top=False, base_url=base_url, relative_uris=relative_uris) return newdict if val is None or isinstance(val, (int, float, bool, str)): return val raise Exception("Not Saveable: %s" % type(val)) def save_with_metadata( val: Any, valLoadingOpts: LoadingOptions, top: bool = True, base_url: str = "", relative_uris: bool = True, ) -> save_type: """Save and set $namespaces, $schemas, $base and any other metadata fields at the top level.""" saved_val: Final = save(val, top, base_url, relative_uris) newdict: MutableMapping[str, Any] = {} if isinstance(saved_val, MutableSequence): newdict = {"$graph": saved_val} elif isinstance(saved_val, MutableMapping): newdict = saved_val if valLoadingOpts.namespaces: newdict["$namespaces"] = valLoadingOpts.namespaces if valLoadingOpts.schemas: newdict["$schemas"] = valLoadingOpts.schemas if valLoadingOpts.baseuri: newdict["$base"] = valLoadingOpts.baseuri for k, v in valLoadingOpts.addl_metadata.items(): if k not in newdict: newdict[k] = v return newdict def expand_url( url: str, base_url: str, loadingOptions: LoadingOptions, scoped_id: bool = False, vocab_term: bool = False, scoped_ref: Optional[int] = None, ) -> str: if url in ("@id", "@type"): return url if vocab_term and url in loadingOptions.vocab: return url if bool(loadingOptions.vocab) and ":" in url: prefix: Final = url.split(":")[0] if prefix in loadingOptions.vocab: url = loadingOptions.vocab[prefix] + url[len(prefix) + 1 :] split1: Final = urlsplit(url) if ( (bool(split1.scheme) and split1.scheme in loadingOptions.fetcher.supported_schemes()) or url.startswith("$(") or url.startswith("${") ): pass elif scoped_id and not bool(split1.fragment): splitbase1: Final = urlsplit(base_url) frg: str if bool(splitbase1.fragment): frg = splitbase1.fragment + "/" + split1.path else: frg = split1.path pt: Final = splitbase1.path if splitbase1.path != "" else "/" url = urlunsplit((splitbase1.scheme, splitbase1.netloc, pt, splitbase1.query, frg)) elif scoped_ref is not None and not bool(split1.fragment): splitbase2: Final = urlsplit(base_url) sp = splitbase2.fragment.split("/") n = scoped_ref while n > 0 and len(sp) > 0: sp.pop() n -= 1 sp.append(url) url = urlunsplit( ( splitbase2.scheme, splitbase2.netloc, splitbase2.path, splitbase2.query, "/".join(sp), ) ) else: url = loadingOptions.fetcher.urljoin(base_url, url) if vocab_term: split2: Final = urlsplit(url) if bool(split2.scheme): if url in loadingOptions.rvocab: return loadingOptions.rvocab[url] else: raise ValidationException(f"Term {url!r} not in vocabulary") return url class _Loader: def load( self, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None, lc: Optional[list[Any]] = None, ) -> Any: pass class _AnyLoader(_Loader): def load( self, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None, lc: Optional[list[Any]] = None, ) -> Any: if doc is not None: return doc raise ValidationException("Expected non-null") class _PrimitiveLoader(_Loader): def __init__(self, tp: Union[type, tuple[type[str], type[str]]]) -> None: self.tp: Final = tp def load( self, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None, lc: Optional[list[Any]] = None, ) -> Any: if not isinstance(doc, self.tp): raise ValidationException(f"Expected a {self.tp} but got {doc.__class__.__name__}") return doc def __repr__(self) -> str: return str(self.tp) class _ArrayLoader(_Loader): def __init__(self, items: _Loader) -> None: self.items: Final = items def load( self, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None, lc: Optional[list[Any]] = None, ) -> Any: if not isinstance(doc, MutableSequence): raise ValidationException( f"Value is a {convert_typing(extract_type(type(doc)))}, " f"but valid type for this field is an array." ) r: Final[list[Any]] = [] errors: Final[list[SchemaSaladException]] = [] fields: Final[list[str]] = [] for i in range(0, len(doc)): try: lf = load_field( doc[i], _UnionLoader([self, self.items]), baseuri, loadingOptions, lc=lc ) flatten = loadingOptions.container != "@list" if flatten and isinstance(lf, MutableSequence): r.extend(lf) else: r.append(lf) if isinstance(doc[i], CommentedMap): if doc[i].get("id") is not None: if doc[i].get("id") in fields: errors.append( ValidationException( f"Duplicate field {doc[i].get('id')!r}", SourceLine(doc[i], "id", str), [], ) ) else: fields.append(doc[i].get("id")) except ValidationException as e: e = ValidationException( "array item is invalid because", SourceLine(doc, i, str), [e] ) errors.append(e) if errors: raise ValidationException("", None, errors) return r def __repr__(self) -> str: return f"array<{self.items}>" class _MapLoader(_Loader): def __init__( self, values: _Loader, name: Optional[str] = None, container: Optional[str] = None, no_link_check: Optional[bool] = None, ) -> None: self.values: Final = values self.name: Final = name self.container: Final = container self.no_link_check: Final = no_link_check def load( self, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None, lc: Optional[list[Any]] = None, ) -> Any: if not isinstance(doc, MutableMapping): raise ValidationException(f"Expected a map, was {type(doc)}") if self.container is not None or self.no_link_check is not None: loadingOptions = LoadingOptions( copyfrom=loadingOptions, container=self.container, no_link_check=self.no_link_check ) r: Final[dict[str, Any]] = {} errors: Final[list[SchemaSaladException]] = [] for k, v in doc.items(): try: lf = load_field(v, self.values, baseuri, loadingOptions, lc) r[k] = lf except ValidationException as e: errors.append(e.with_sourceline(SourceLine(doc, k, str))) if errors: raise ValidationException("", None, errors) return r def __repr__(self) -> str: return self.name if self.name is not None else f"map" class _EnumLoader(_Loader): def __init__(self, symbols: Sequence[str], name: str) -> None: self.symbols: Final = symbols self.name: Final = name def load( self, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None, lc: Optional[list[Any]] = None, ) -> Any: if doc in self.symbols: return doc raise ValidationException(f"Expected one of {self.symbols}") def __repr__(self) -> str: return self.name class _SecondaryDSLLoader(_Loader): def __init__(self, inner: _Loader) -> None: self.inner: Final = inner def load( self, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None, lc: Optional[list[Any]] = None, ) -> Any: r: Final[list[dict[str, Any]]] = [] if isinstance(doc, MutableSequence): for d in doc: if isinstance(d, str): if d.endswith("?"): r.append({"pattern": d[:-1], "required": False}) else: r.append({"pattern": d}) elif isinstance(d, dict): new_dict1: dict[str, Any] = {} dict_copy = copy.deepcopy(d) if "pattern" in dict_copy: new_dict1["pattern"] = dict_copy.pop("pattern") else: raise ValidationException( f"Missing pattern in secondaryFiles specification entry: {d}" ) new_dict1["required"] = ( dict_copy.pop("required") if "required" in dict_copy else None ) if len(dict_copy): raise ValidationException( "Unallowed values in secondaryFiles specification entry: {}".format( dict_copy ) ) r.append(new_dict1) else: raise ValidationException( "Expected a string or sequence of (strings or mappings)." ) elif isinstance(doc, MutableMapping): new_dict2: Final = {} doc_copy: Final = copy.deepcopy(doc) if "pattern" in doc_copy: new_dict2["pattern"] = doc_copy.pop("pattern") else: raise ValidationException( f"Missing pattern in secondaryFiles specification entry: {doc}" ) new_dict2["required"] = doc_copy.pop("required") if "required" in doc_copy else None if len(doc_copy): raise ValidationException( f"Unallowed values in secondaryFiles specification entry: {doc_copy}" ) r.append(new_dict2) elif isinstance(doc, str): if doc.endswith("?"): r.append({"pattern": doc[:-1], "required": False}) else: r.append({"pattern": doc}) else: raise ValidationException("Expected str or sequence of str") return self.inner.load(r, baseuri, loadingOptions, docRoot, lc=lc) class _RecordLoader(_Loader): def __init__( self, classtype: type[Saveable], container: Optional[str] = None, no_link_check: Optional[bool] = None, ) -> None: self.classtype: Final = classtype self.container: Final = container self.no_link_check: Final = no_link_check def load( self, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None, lc: Optional[list[Any]] = None, ) -> Any: if not isinstance(doc, MutableMapping): raise ValidationException( f"Value is a {convert_typing(extract_type(type(doc)))}, " f"but valid type for this field is an object." ) if self.container is not None or self.no_link_check is not None: loadingOptions = LoadingOptions( copyfrom=loadingOptions, container=self.container, no_link_check=self.no_link_check ) return self.classtype.fromDoc(doc, baseuri, loadingOptions, docRoot=docRoot) def __repr__(self) -> str: return str(self.classtype.__name__) class _ExpressionLoader(_Loader): def __init__(self, items: type[str]) -> None: self.items: Final = items def load( self, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None, lc: Optional[list[Any]] = None, ) -> Any: if not isinstance(doc, str): raise ValidationException( f"Value is a {convert_typing(extract_type(type(doc)))}, " f"but valid type for this field is a str." ) return doc class _UnionLoader(_Loader): def __init__(self, alternates: Sequence[_Loader], name: Optional[str] = None) -> None: self.alternates = alternates self.name: Final = name def add_loaders(self, loaders: Sequence[_Loader]) -> None: self.alternates = tuple(loader for loader in chain(self.alternates, loaders)) def load( self, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None, lc: Optional[list[Any]] = None, ) -> Any: errors: Final = [] if lc is None: lc = [] for t in self.alternates: try: return t.load(doc, baseuri, loadingOptions, docRoot=docRoot, lc=lc) except ValidationException as e: if isinstance(t, _ArrayLoader) and len(self.alternates) > 1: continue if isinstance(doc, (CommentedMap, dict)): if "class" in doc: if str(doc.get("class")) == str(t): errors.append( ValidationException( f"Object `{baseuri.split('/')[-1]}` is not valid because:", SourceLine(doc, next(iter(doc)), str), [e], ) ) else: if "array" in str(t): continue else: if "id" in doc: id = baseuri.split("/")[-1] + "#" + str(doc.get("id")) if "id" in lc: errors.append( ValidationException( f"checking object `{id}` using `{t}`", SourceLine(lc, "id", str), [e], ) ) else: errors.append( ValidationException( f"checking object `{id}` using `{t}`", SourceLine(lc, doc.get("id"), str), [e], ) ) else: if not isinstance( t, (_PrimitiveLoader) ): # avoids 'tried was {x}' errors errors.append( ValidationException(f"tried `{t}` but", None, [e]) ) else: # avoids "tried but x" and instead returns the values for parsing errors.append(ValidationException("", None, [e])) if isinstance(doc, (CommentedMap, dict)) and "class" in doc: if str(doc.get("class")) not in str(self.alternates): errors.append( ValidationException( "Field `class` contains undefined reference to " + "`" + "/".join(baseuri.split("/")[0:-1]) + "/" + str(doc.get("class")) + "`", SourceLine(doc, "class", str), [], ) ) raise ValidationException("", None, errors, "*") def __repr__(self) -> str: return self.name if self.name is not None else " | ".join(str(a) for a in self.alternates) class _URILoader(_Loader): def __init__( self, inner: _Loader, scoped_id: bool, vocab_term: bool, scoped_ref: Optional[int], no_link_check: Optional[bool], ) -> None: self.inner: Final = inner self.scoped_id: Final = scoped_id self.vocab_term: Final = vocab_term self.scoped_ref: Final = scoped_ref self.no_link_check: Final = no_link_check def load( self, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None, lc: Optional[list[Any]] = None, ) -> Any: if self.no_link_check is not None: loadingOptions = LoadingOptions( copyfrom=loadingOptions, no_link_check=self.no_link_check ) if isinstance(doc, MutableSequence): newdoc: Final = [] for i in doc: if isinstance(i, str): newdoc.append( expand_url( i, baseuri, loadingOptions, self.scoped_id, self.vocab_term, self.scoped_ref, ) ) else: newdoc.append(i) doc = newdoc elif isinstance(doc, str): doc = expand_url( doc, baseuri, loadingOptions, self.scoped_id, self.vocab_term, self.scoped_ref, ) if isinstance(doc, str): if not loadingOptions.no_link_check: errors: Final = [] try: if not loadingOptions.fetcher.check_exists(doc): errors.append( ValidationException(f"contains undefined reference to `{doc}`") ) except ValidationException: pass if len(errors) > 0: raise ValidationException("", None, errors) return self.inner.load(doc, baseuri, loadingOptions, lc=lc) class _TypeDSLLoader(_Loader): def __init__(self, inner: _Loader, refScope: Optional[int], salad_version: str) -> None: self.inner: Final = inner self.refScope: Final = refScope self.salad_version: Final = salad_version def resolve( self, doc: str, baseuri: str, loadingOptions: LoadingOptions, ) -> Union[list[Union[dict[str, Any], str]], dict[str, Any], str]: doc_ = doc optional = False if doc_.endswith("?"): optional = True doc_ = doc_[0:-1] if doc_.endswith("[]"): salad_versions: Final = [int(v) for v in self.salad_version[1:].split(".")] items: Union[list[Union[dict[str, Any], str]], dict[str, Any], str] = "" rest: Final = doc_[0:-2] if salad_versions < [1, 3]: if rest.endswith("[]"): # To show the error message with the original type return doc else: items = expand_url(rest, baseuri, loadingOptions, False, True, self.refScope) else: items = self.resolve(rest, baseuri, loadingOptions) if isinstance(items, str): items = expand_url(items, baseuri, loadingOptions, False, True, self.refScope) expanded: Union[dict[str, Any], str] = {"type": "array", "items": items} else: expanded = expand_url(doc_, baseuri, loadingOptions, False, True, self.refScope) if optional: return ["null", expanded] else: return expanded def load( self, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None, lc: Optional[list[Any]] = None, ) -> Any: if isinstance(doc, MutableSequence): r: Final[list[Any]] = [] for d in doc: if isinstance(d, str): resolved = self.resolve(d, baseuri, loadingOptions) if isinstance(resolved, MutableSequence): for i in resolved: if i not in r: r.append(i) else: if resolved not in r: r.append(resolved) else: r.append(d) doc = r elif isinstance(doc, str): doc = self.resolve(doc, baseuri, loadingOptions) return self.inner.load(doc, baseuri, loadingOptions, lc=lc) class _IdMapLoader(_Loader): def __init__(self, inner: _Loader, mapSubject: str, mapPredicate: Optional[str]) -> None: self.inner: Final = inner self.mapSubject: Final = mapSubject self.mapPredicate: Final = mapPredicate def load( self, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None, lc: Optional[list[Any]] = None, ) -> Any: if isinstance(doc, MutableMapping): r: Final[list[Any]] = [] for k in doc.keys(): val = doc[k] if isinstance(val, CommentedMap): v = copy.copy(val) v.lc.data = val.lc.data v.lc.filename = val.lc.filename v[self.mapSubject] = k r.append(v) elif isinstance(val, MutableMapping): v2 = copy.copy(val) v2[self.mapSubject] = k r.append(v2) else: if self.mapPredicate: v3 = {self.mapPredicate: val} v3[self.mapSubject] = k r.append(v3) else: raise ValidationException("No mapPredicate") doc = r return self.inner.load(doc, baseuri, loadingOptions, lc=lc) def _document_load( loader: _Loader, doc: Union[str, MutableMapping[str, Any], MutableSequence[Any]], baseuri: str, loadingOptions: LoadingOptions, addl_metadata_fields: Optional[MutableSequence[str]] = None, ) -> tuple[Any, LoadingOptions]: if isinstance(doc, str): return _document_load_by_url( loader, loadingOptions.fetcher.urljoin(baseuri, doc), loadingOptions, addl_metadata_fields=addl_metadata_fields, ) if isinstance(doc, MutableMapping): addl_metadata: Final = {} if addl_metadata_fields is not None: for mf in addl_metadata_fields: if mf in doc: addl_metadata[mf] = doc[mf] docuri: Final = baseuri if "$base" in doc: baseuri = doc["$base"] loadingOptions = LoadingOptions( copyfrom=loadingOptions, namespaces=doc.get("$namespaces", None), schemas=doc.get("$schemas", None), baseuri=doc.get("$base", None), addl_metadata=addl_metadata, ) doc2: Final = copy.copy(doc) if "$namespaces" in doc2: doc2.pop("$namespaces") if "$schemas" in doc2: doc2.pop("$schemas") if "$base" in doc2: doc2.pop("$base") if "$graph" in doc2: loadingOptions.idx[baseuri] = ( loader.load(doc2["$graph"], baseuri, loadingOptions), loadingOptions, ) else: loadingOptions.idx[baseuri] = ( loader.load(doc2, baseuri, loadingOptions, docRoot=baseuri), loadingOptions, ) if docuri != baseuri: loadingOptions.idx[docuri] = loadingOptions.idx[baseuri] return loadingOptions.idx[baseuri] if isinstance(doc, MutableSequence): loadingOptions.idx[baseuri] = ( loader.load(doc, baseuri, loadingOptions), loadingOptions, ) return loadingOptions.idx[baseuri] raise ValidationException( "Expected URI string, MutableMapping or MutableSequence, got %s" % type(doc) ) def _document_load_by_url( loader: _Loader, url: str, loadingOptions: LoadingOptions, addl_metadata_fields: Optional[MutableSequence[str]] = None, ) -> tuple[Any, LoadingOptions]: if url in loadingOptions.idx: return loadingOptions.idx[url] doc_url, frg = urldefrag(url) text: Final = loadingOptions.fetcher.fetch_text(doc_url) textIO: Final = StringIO(text) textIO.name = str(doc_url) yaml: Final = yaml_no_ts() result: Final = yaml.load(textIO) add_lc_filename(result, doc_url) loadingOptions = LoadingOptions(copyfrom=loadingOptions, fileuri=doc_url) _document_load( loader, result, doc_url, loadingOptions, addl_metadata_fields=addl_metadata_fields, ) return loadingOptions.idx[url] def file_uri(path: str, split_frag: bool = False) -> str: """Transform a file path into a URL with file scheme.""" if path.startswith("file://"): return path if split_frag: pathsp: Final = path.split("#", 2) frag = "#" + quote(str(pathsp[1])) if len(pathsp) == 2 else "" urlpath = pathname2url(str(pathsp[0])) else: urlpath = pathname2url(path) frag = "" if urlpath.startswith("//"): return f"file:{urlpath}{frag}" return f"file://{urlpath}{frag}" def prefix_url(url: str, namespaces: dict[str, str]) -> str: """Expand short forms into full URLs using the given namespace dictionary.""" for k, v in namespaces.items(): if url.startswith(v): return k + ":" + url[len(v) :] return url def save_relative_uri( uri: Any, base_url: str, scoped_id: bool, ref_scope: Optional[int], relative_uris: bool, ) -> Any: """Convert any URI to a relative one, obeying the scoping rules.""" if isinstance(uri, MutableSequence): return [save_relative_uri(u, base_url, scoped_id, ref_scope, relative_uris) for u in uri] elif isinstance(uri, str): if not relative_uris or uri == base_url: return uri urisplit: Final = urlsplit(uri) basesplit: Final = urlsplit(base_url) if urisplit.scheme == basesplit.scheme and urisplit.netloc == basesplit.netloc: if urisplit.path != basesplit.path: p = os.path.relpath(urisplit.path, os.path.dirname(basesplit.path)) if urisplit.fragment: p = p + "#" + urisplit.fragment return p basefrag = basesplit.fragment + "/" if ref_scope: sp = basefrag.split("/") i = 0 while i < ref_scope: sp.pop() i += 1 basefrag = "/".join(sp) if urisplit.fragment.startswith(basefrag): return urisplit.fragment[len(basefrag) :] return urisplit.fragment return uri else: return save(uri, top=False, base_url=base_url, relative_uris=relative_uris) def shortname(inputid: str) -> str: """ Compute the shortname of a fully qualified identifier. See https://w3id.org/cwl/v1.2/SchemaSalad.html#Short_names. """ parsed_id: Final = urlparse(inputid) if parsed_id.fragment: return parsed_id.fragment.split("/")[-1] return parsed_id.path.split("/")[-1] def parser_info() -> str: return "org.w3id.cwl.v1_0" class Documented(Saveable): pass class RecordField(Documented): """ A field of a record. """ name: str def __init__( self, name: Any, type_: Any, doc: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.doc = doc self.name = name if name is not None else "_:" + str(_uuid__.uuid4()) self.type_ = type_ def __eq__(self, other: Any) -> bool: if isinstance(other, RecordField): return bool( self.doc == other.doc and self.name == other.name and self.type_ == other.type_ ) return False def __hash__(self) -> int: return hash((self.doc, self.name, self.type_)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "RecordField": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] name = None if "name" in _doc: try: name = load_field( _doc.get("name"), uri_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("name") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `name`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("name") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [e], detailed_message=f"the `name` field with value `{val}` " "is not valid because:", ) ) __original_name_is_none = name is None if name is None: if docRoot is not None: name = docRoot else: _errors__.append(ValidationException("missing name")) if not __original_name_is_none: baseuri = cast(str, name) doc = None if "doc" in _doc: try: doc = load_field( _doc.get("doc"), union_of_None_type_or_strtype_or_array_of_strtype, baseuri, loadingOptions, lc=_doc.get("doc") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `doc`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("doc") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [e], detailed_message=f"the `doc` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("type") is None: raise ValidationException("missing required field `type`", None, []) type_ = load_field( _doc.get("type"), typedsl_union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype_or_array_of_union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype_2, baseuri, loadingOptions, lc=_doc.get("type") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `type`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("type") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [e], detailed_message=f"the `type` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `doc`, `name`, `type`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( doc=doc, name=name, type_=type_, extension_fields=extension_fields, loadingOptions=loadingOptions, ) loadingOptions.idx[cast(str, name)] = (_constructed, loadingOptions) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.name is not None: u = save_relative_uri(self.name, base_url, True, None, relative_uris) r["name"] = u if self.doc is not None: r["doc"] = save( self.doc, top=False, base_url=self.name, relative_uris=relative_uris ) if self.type_ is not None: r["type"] = save( self.type_, top=False, base_url=self.name, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["doc", "name", "type"]) class RecordSchema(Saveable): def __init__( self, type_: Any, fields: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.fields = fields self.type_ = type_ def __eq__(self, other: Any) -> bool: if isinstance(other, RecordSchema): return bool(self.fields == other.fields and self.type_ == other.type_) return False def __hash__(self) -> int: return hash((self.fields, self.type_)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "RecordSchema": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] fields = None if "fields" in _doc: try: fields = load_field( _doc.get("fields"), idmap_fields_union_of_None_type_or_array_of_RecordFieldLoader, baseuri, loadingOptions, lc=_doc.get("fields") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `fields`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("fields") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `fields` field is not valid because:", SourceLine(_doc, "fields", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `fields` field is not valid because:", SourceLine(_doc, "fields", str), [e], detailed_message=f"the `fields` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("type") is None: raise ValidationException("missing required field `type`", None, []) type_ = load_field( _doc.get("type"), typedsl_Record_nameLoader_2, baseuri, loadingOptions, lc=_doc.get("type") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `type`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("type") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [e], detailed_message=f"the `type` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `fields`, `type`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( fields=fields, type_=type_, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.fields is not None: r["fields"] = save( self.fields, top=False, base_url=base_url, relative_uris=relative_uris ) if self.type_ is not None: r["type"] = save( self.type_, top=False, base_url=base_url, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["fields", "type"]) class EnumSchema(Saveable): """ Define an enumerated type. """ name: str def __init__( self, symbols: Any, type_: Any, name: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.name = name if name is not None else "_:" + str(_uuid__.uuid4()) self.symbols = symbols self.type_ = type_ def __eq__(self, other: Any) -> bool: if isinstance(other, EnumSchema): return bool( self.name == other.name and self.symbols == other.symbols and self.type_ == other.type_ ) return False def __hash__(self) -> int: return hash((self.name, self.symbols, self.type_)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "EnumSchema": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] name = None if "name" in _doc: try: name = load_field( _doc.get("name"), uri_union_of_None_type_or_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("name") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `name`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("name") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [e], detailed_message=f"the `name` field with value `{val}` " "is not valid because:", ) ) __original_name_is_none = name is None if name is None: if docRoot is not None: name = docRoot else: name = "_:" + str(_uuid__.uuid4()) if not __original_name_is_none: baseuri = cast(str, name) try: if _doc.get("symbols") is None: raise ValidationException("missing required field `symbols`", None, []) symbols = load_field( _doc.get("symbols"), uri_array_of_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("symbols") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `symbols`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("symbols") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `symbols` field is not valid because:", SourceLine(_doc, "symbols", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `symbols` field is not valid because:", SourceLine(_doc, "symbols", str), [e], detailed_message=f"the `symbols` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("type") is None: raise ValidationException("missing required field `type`", None, []) type_ = load_field( _doc.get("type"), typedsl_Enum_nameLoader_2, baseuri, loadingOptions, lc=_doc.get("type") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `type`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("type") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [e], detailed_message=f"the `type` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `name`, `symbols`, `type`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( name=name, symbols=symbols, type_=type_, extension_fields=extension_fields, loadingOptions=loadingOptions, ) loadingOptions.idx[cast(str, name)] = (_constructed, loadingOptions) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.name is not None: u = save_relative_uri(self.name, base_url, True, None, relative_uris) r["name"] = u if self.symbols is not None: u = save_relative_uri(self.symbols, self.name, True, None, relative_uris) r["symbols"] = u if self.type_ is not None: r["type"] = save( self.type_, top=False, base_url=self.name, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["name", "symbols", "type"]) class ArraySchema(Saveable): def __init__( self, items: Any, type_: Any, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.items = items self.type_ = type_ def __eq__(self, other: Any) -> bool: if isinstance(other, ArraySchema): return bool(self.items == other.items and self.type_ == other.type_) return False def __hash__(self) -> int: return hash((self.items, self.type_)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "ArraySchema": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("items") is None: raise ValidationException("missing required field `items`", None, []) items = load_field( _doc.get("items"), uri_union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype_or_array_of_union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype_False_True_2_None, baseuri, loadingOptions, lc=_doc.get("items") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `items`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("items") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `items` field is not valid because:", SourceLine(_doc, "items", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `items` field is not valid because:", SourceLine(_doc, "items", str), [e], detailed_message=f"the `items` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("type") is None: raise ValidationException("missing required field `type`", None, []) type_ = load_field( _doc.get("type"), typedsl_Array_nameLoader_2, baseuri, loadingOptions, lc=_doc.get("type") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `type`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("type") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [e], detailed_message=f"the `type` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `items`, `type`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( items=items, type_=type_, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.items is not None: u = save_relative_uri(self.items, base_url, False, 2, relative_uris) r["items"] = u if self.type_ is not None: r["type"] = save( self.type_, top=False, base_url=base_url, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["items", "type"]) class MapSchema(Saveable): def __init__( self, type_: Any, values: Any, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.type_ = type_ self.values = values def __eq__(self, other: Any) -> bool: if isinstance(other, MapSchema): return bool(self.type_ == other.type_ and self.values == other.values) return False def __hash__(self) -> int: return hash((self.type_, self.values)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "MapSchema": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("type") is None: raise ValidationException("missing required field `type`", None, []) type_ = load_field( _doc.get("type"), typedsl_Map_nameLoader_2, baseuri, loadingOptions, lc=_doc.get("type") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `type`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("type") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [e], detailed_message=f"the `type` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("values") is None: raise ValidationException("missing required field `values`", None, []) values = load_field( _doc.get("values"), uri_union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype_or_array_of_union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype_False_True_2_None, baseuri, loadingOptions, lc=_doc.get("values") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `values`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("values") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `values` field is not valid because:", SourceLine(_doc, "values", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `values` field is not valid because:", SourceLine(_doc, "values", str), [e], detailed_message=f"the `values` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `type`, `values`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( type_=type_, values=values, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.type_ is not None: r["type"] = save( self.type_, top=False, base_url=base_url, relative_uris=relative_uris ) if self.values is not None: u = save_relative_uri(self.values, base_url, False, 2, relative_uris) r["values"] = u # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["type", "values"]) class UnionSchema(Saveable): def __init__( self, names: Any, type_: Any, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.names = names self.type_ = type_ def __eq__(self, other: Any) -> bool: if isinstance(other, UnionSchema): return bool(self.names == other.names and self.type_ == other.type_) return False def __hash__(self) -> int: return hash((self.names, self.type_)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "UnionSchema": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("names") is None: raise ValidationException("missing required field `names`", None, []) names = load_field( _doc.get("names"), uri_union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype_or_array_of_union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype_False_True_2_None, baseuri, loadingOptions, lc=_doc.get("names") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `names`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("names") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `names` field is not valid because:", SourceLine(_doc, "names", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `names` field is not valid because:", SourceLine(_doc, "names", str), [e], detailed_message=f"the `names` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("type") is None: raise ValidationException("missing required field `type`", None, []) type_ = load_field( _doc.get("type"), typedsl_Union_nameLoader_2, baseuri, loadingOptions, lc=_doc.get("type") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `type`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("type") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [e], detailed_message=f"the `type` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `names`, `type`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( names=names, type_=type_, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.names is not None: u = save_relative_uri(self.names, base_url, False, 2, relative_uris) r["names"] = u if self.type_ is not None: r["type"] = save( self.type_, top=False, base_url=base_url, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["names", "type"]) class CWLArraySchema(ArraySchema): def __init__( self, items: Any, type_: Any, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.items = items self.type_ = type_ def __eq__(self, other: Any) -> bool: if isinstance(other, CWLArraySchema): return bool(self.items == other.items and self.type_ == other.type_) return False def __hash__(self) -> int: return hash((self.items, self.type_)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "CWLArraySchema": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("items") is None: raise ValidationException("missing required field `items`", None, []) items = load_field( _doc.get("items"), uri_union_of_PrimitiveTypeLoader_or_CWLRecordSchemaLoader_or_EnumSchemaLoader_or_CWLArraySchemaLoader_or_strtype_or_array_of_union_of_PrimitiveTypeLoader_or_CWLRecordSchemaLoader_or_EnumSchemaLoader_or_CWLArraySchemaLoader_or_strtype_False_True_2_None, baseuri, loadingOptions, lc=_doc.get("items") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `items`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("items") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `items` field is not valid because:", SourceLine(_doc, "items", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `items` field is not valid because:", SourceLine(_doc, "items", str), [e], detailed_message=f"the `items` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("type") is None: raise ValidationException("missing required field `type`", None, []) type_ = load_field( _doc.get("type"), typedsl_Array_nameLoader_2, baseuri, loadingOptions, lc=_doc.get("type") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `type`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("type") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [e], detailed_message=f"the `type` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `items`, `type`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( items=items, type_=type_, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.items is not None: u = save_relative_uri(self.items, base_url, False, 2, relative_uris) r["items"] = u if self.type_ is not None: r["type"] = save( self.type_, top=False, base_url=base_url, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["items", "type"]) class CWLRecordField(RecordField): name: str def __init__( self, name: Any, type_: Any, doc: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.doc = doc self.name = name if name is not None else "_:" + str(_uuid__.uuid4()) self.type_ = type_ def __eq__(self, other: Any) -> bool: if isinstance(other, CWLRecordField): return bool( self.doc == other.doc and self.name == other.name and self.type_ == other.type_ ) return False def __hash__(self) -> int: return hash((self.doc, self.name, self.type_)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "CWLRecordField": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] name = None if "name" in _doc: try: name = load_field( _doc.get("name"), uri_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("name") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `name`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("name") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [e], detailed_message=f"the `name` field with value `{val}` " "is not valid because:", ) ) __original_name_is_none = name is None if name is None: if docRoot is not None: name = docRoot else: _errors__.append(ValidationException("missing name")) if not __original_name_is_none: baseuri = cast(str, name) doc = None if "doc" in _doc: try: doc = load_field( _doc.get("doc"), union_of_None_type_or_strtype_or_array_of_strtype, baseuri, loadingOptions, lc=_doc.get("doc") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `doc`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("doc") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [e], detailed_message=f"the `doc` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("type") is None: raise ValidationException("missing required field `type`", None, []) type_ = load_field( _doc.get("type"), typedsl_union_of_PrimitiveTypeLoader_or_CWLRecordSchemaLoader_or_EnumSchemaLoader_or_CWLArraySchemaLoader_or_strtype_or_array_of_union_of_PrimitiveTypeLoader_or_CWLRecordSchemaLoader_or_EnumSchemaLoader_or_CWLArraySchemaLoader_or_strtype_2, baseuri, loadingOptions, lc=_doc.get("type") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `type`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("type") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [e], detailed_message=f"the `type` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `doc`, `name`, `type`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( doc=doc, name=name, type_=type_, extension_fields=extension_fields, loadingOptions=loadingOptions, ) loadingOptions.idx[cast(str, name)] = (_constructed, loadingOptions) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.name is not None: u = save_relative_uri(self.name, base_url, True, None, relative_uris) r["name"] = u if self.doc is not None: r["doc"] = save( self.doc, top=False, base_url=self.name, relative_uris=relative_uris ) if self.type_ is not None: r["type"] = save( self.type_, top=False, base_url=self.name, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["doc", "name", "type"]) class CWLRecordSchema(RecordSchema): def __init__( self, type_: Any, fields: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.fields = fields self.type_ = type_ def __eq__(self, other: Any) -> bool: if isinstance(other, CWLRecordSchema): return bool(self.fields == other.fields and self.type_ == other.type_) return False def __hash__(self) -> int: return hash((self.fields, self.type_)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "CWLRecordSchema": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] fields = None if "fields" in _doc: try: fields = load_field( _doc.get("fields"), idmap_fields_union_of_None_type_or_array_of_CWLRecordFieldLoader, baseuri, loadingOptions, lc=_doc.get("fields") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `fields`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("fields") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `fields` field is not valid because:", SourceLine(_doc, "fields", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `fields` field is not valid because:", SourceLine(_doc, "fields", str), [e], detailed_message=f"the `fields` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("type") is None: raise ValidationException("missing required field `type`", None, []) type_ = load_field( _doc.get("type"), typedsl_Record_nameLoader_2, baseuri, loadingOptions, lc=_doc.get("type") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `type`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("type") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [e], detailed_message=f"the `type` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `fields`, `type`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( fields=fields, type_=type_, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.fields is not None: r["fields"] = save( self.fields, top=False, base_url=base_url, relative_uris=relative_uris ) if self.type_ is not None: r["type"] = save( self.type_, top=False, base_url=base_url, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["fields", "type"]) class File(Saveable): """ Represents a file (or group of files when `secondaryFiles` is provided) that will be accessible by tools using standard POSIX file system call API such as open(2) and read(2). Files are represented as objects with `class` of `File`. File objects have a number of properties that provide metadata about the file. The `location` property of a File is a URI that uniquely identifies the file. Implementations must support the file:// URI scheme and may support other schemes such as http://. The value of `location` may also be a relative reference, in which case it must be resolved relative to the URI of the document it appears in. Alternately to `location`, implementations must also accept the `path` property on File, which must be a filesystem path available on the same host as the CWL runner (for inputs) or the runtime environment of a command line tool execution (for command line tool outputs). If no `location` or `path` is specified, a file object must specify `contents` with the UTF-8 text content of the file. This is a "file literal". File literals do not correspond to external resources, but are created on disk with `contents` with when needed for a executing a tool. Where appropriate, expressions can return file literals to define new files on a runtime. The maximum size of `contents` is 64 kilobytes. The `basename` property defines the filename on disk where the file is staged. This may differ from the resource name. If not provided, `basename` must be computed from the last path part of `location` and made available to expressions. The `secondaryFiles` property is a list of File or Directory objects that must be staged in the same directory as the primary file. It is an error for file names to be duplicated in `secondaryFiles`. The `size` property is the size in bytes of the File. It must be computed from the resource and made available to expressions. The `checksum` field contains a cryptographic hash of the file content for use it verifying file contents. Implementations may, at user option, enable or disable computation of the `checksum` field for performance or other reasons. However, the ability to compute output checksums is required to pass the CWL conformance test suite. When executing a CommandLineTool, the files and secondary files may be staged to an arbitrary directory, but must use the value of `basename` for the filename. The `path` property must be file path in the context of the tool execution runtime (local to the compute node, or within the executing container). All computed properties should be available to expressions. File literals also must be staged and `path` must be set. When collecting CommandLineTool outputs, `glob` matching returns file paths (with the `path` property) and the derived properties. This can all be modified by `outputEval`. Alternately, if the file `cwl.output.json` is present in the output, `outputBinding` is ignored. File objects in the output must provide either a `location` URI or a `path` property in the context of the tool execution runtime (local to the compute node, or within the executing container). When evaluating an ExpressionTool, file objects must be referenced via `location` (the expression tool does not have access to files on disk so `path` is meaningless) or as file literals. It is legal to return a file object with an existing `location` but a different `basename`. The `loadContents` field of ExpressionTool inputs behaves the same as on CommandLineTool inputs, however it is not meaningful on the outputs. An ExpressionTool may forward file references from input to output by using the same value for `location`. """ def __init__( self, location: Optional[Any] = None, path: Optional[Any] = None, basename: Optional[Any] = None, dirname: Optional[Any] = None, nameroot: Optional[Any] = None, nameext: Optional[Any] = None, checksum: Optional[Any] = None, size: Optional[Any] = None, secondaryFiles: Optional[Any] = None, format: Optional[Any] = None, contents: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.class_ = "File" self.location = location self.path = path self.basename = basename self.dirname = dirname self.nameroot = nameroot self.nameext = nameext self.checksum = checksum self.size = size self.secondaryFiles = secondaryFiles self.format = format self.contents = contents def __eq__(self, other: Any) -> bool: if isinstance(other, File): return bool( self.class_ == other.class_ and self.location == other.location and self.path == other.path and self.basename == other.basename and self.dirname == other.dirname and self.nameroot == other.nameroot and self.nameext == other.nameext and self.checksum == other.checksum and self.size == other.size and self.secondaryFiles == other.secondaryFiles and self.format == other.format and self.contents == other.contents ) return False def __hash__(self) -> int: return hash( ( self.class_, self.location, self.path, self.basename, self.dirname, self.nameroot, self.nameext, self.checksum, self.size, self.secondaryFiles, self.format, self.contents, ) ) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "File": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("class") is None: raise ValidationException("missing required field `class`", None, []) class_ = load_field( _doc.get("class"), uri_File_classLoader_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("class") ) if class_ not in (cls.__name__, loadingOptions.vocab.get(cls.__name__)): raise ValidationException(f"tried `{cls.__name__}` but") except ValidationException as e: raise e location = None if "location" in _doc: try: location = load_field( _doc.get("location"), uri_union_of_None_type_or_strtype_False_False_None_None, baseuri, loadingOptions, lc=_doc.get("location") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `location`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("location") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `location` field is not valid because:", SourceLine(_doc, "location", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `location` field is not valid because:", SourceLine(_doc, "location", str), [e], detailed_message=f"the `location` field with value `{val}` " "is not valid because:", ) ) path = None if "path" in _doc: try: path = load_field( _doc.get("path"), uri_union_of_None_type_or_strtype_False_False_None_None, baseuri, loadingOptions, lc=_doc.get("path") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `path`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("path") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `path` field is not valid because:", SourceLine(_doc, "path", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `path` field is not valid because:", SourceLine(_doc, "path", str), [e], detailed_message=f"the `path` field with value `{val}` " "is not valid because:", ) ) basename = None if "basename" in _doc: try: basename = load_field( _doc.get("basename"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("basename") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `basename`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("basename") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `basename` field is not valid because:", SourceLine(_doc, "basename", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `basename` field is not valid because:", SourceLine(_doc, "basename", str), [e], detailed_message=f"the `basename` field with value `{val}` " "is not valid because:", ) ) dirname = None if "dirname" in _doc: try: dirname = load_field( _doc.get("dirname"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("dirname") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `dirname`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("dirname") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `dirname` field is not valid because:", SourceLine(_doc, "dirname", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `dirname` field is not valid because:", SourceLine(_doc, "dirname", str), [e], detailed_message=f"the `dirname` field with value `{val}` " "is not valid because:", ) ) nameroot = None if "nameroot" in _doc: try: nameroot = load_field( _doc.get("nameroot"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("nameroot") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `nameroot`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("nameroot") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `nameroot` field is not valid because:", SourceLine(_doc, "nameroot", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `nameroot` field is not valid because:", SourceLine(_doc, "nameroot", str), [e], detailed_message=f"the `nameroot` field with value `{val}` " "is not valid because:", ) ) nameext = None if "nameext" in _doc: try: nameext = load_field( _doc.get("nameext"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("nameext") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `nameext`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("nameext") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `nameext` field is not valid because:", SourceLine(_doc, "nameext", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `nameext` field is not valid because:", SourceLine(_doc, "nameext", str), [e], detailed_message=f"the `nameext` field with value `{val}` " "is not valid because:", ) ) checksum = None if "checksum" in _doc: try: checksum = load_field( _doc.get("checksum"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("checksum") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `checksum`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("checksum") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `checksum` field is not valid because:", SourceLine(_doc, "checksum", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `checksum` field is not valid because:", SourceLine(_doc, "checksum", str), [e], detailed_message=f"the `checksum` field with value `{val}` " "is not valid because:", ) ) size = None if "size" in _doc: try: size = load_field( _doc.get("size"), union_of_None_type_or_inttype, baseuri, loadingOptions, lc=_doc.get("size") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `size`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("size") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `size` field is not valid because:", SourceLine(_doc, "size", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `size` field is not valid because:", SourceLine(_doc, "size", str), [e], detailed_message=f"the `size` field with value `{val}` " "is not valid because:", ) ) secondaryFiles = None if "secondaryFiles" in _doc: try: secondaryFiles = load_field( _doc.get("secondaryFiles"), union_of_None_type_or_array_of_union_of_FileLoader_or_DirectoryLoader, baseuri, loadingOptions, lc=_doc.get("secondaryFiles") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `secondaryFiles`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("secondaryFiles") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `secondaryFiles` field is not valid because:", SourceLine(_doc, "secondaryFiles", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `secondaryFiles` field is not valid because:", SourceLine(_doc, "secondaryFiles", str), [e], detailed_message=f"the `secondaryFiles` field with value `{val}` " "is not valid because:", ) ) format = None if "format" in _doc: try: format = load_field( _doc.get("format"), uri_union_of_None_type_or_strtype_True_False_None_True, baseuri, loadingOptions, lc=_doc.get("format") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `format`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("format") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `format` field is not valid because:", SourceLine(_doc, "format", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `format` field is not valid because:", SourceLine(_doc, "format", str), [e], detailed_message=f"the `format` field with value `{val}` " "is not valid because:", ) ) contents = None if "contents" in _doc: try: contents = load_field( _doc.get("contents"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("contents") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `contents`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("contents") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `contents` field is not valid because:", SourceLine(_doc, "contents", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `contents` field is not valid because:", SourceLine(_doc, "contents", str), [e], detailed_message=f"the `contents` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `class`, `location`, `path`, `basename`, `dirname`, `nameroot`, `nameext`, `checksum`, `size`, `secondaryFiles`, `format`, `contents`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( location=location, path=path, basename=basename, dirname=dirname, nameroot=nameroot, nameext=nameext, checksum=checksum, size=size, secondaryFiles=secondaryFiles, format=format, contents=contents, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.class_ is not None: uri = self.loadingOptions.vocab[self.class_] if p := self.loadingOptions.rvocab.get(uri[: -len(self.class_)]): uri = f"{p}:{self.class_}" else: uri = self.class_ u = save_relative_uri(uri, base_url, False, None, relative_uris) r["class"] = u if self.location is not None: u = save_relative_uri(self.location, base_url, False, None, relative_uris) r["location"] = u if self.path is not None: u = save_relative_uri(self.path, base_url, False, None, relative_uris) r["path"] = u if self.basename is not None: r["basename"] = save( self.basename, top=False, base_url=base_url, relative_uris=relative_uris ) if self.dirname is not None: r["dirname"] = save( self.dirname, top=False, base_url=base_url, relative_uris=relative_uris ) if self.nameroot is not None: r["nameroot"] = save( self.nameroot, top=False, base_url=base_url, relative_uris=relative_uris ) if self.nameext is not None: r["nameext"] = save( self.nameext, top=False, base_url=base_url, relative_uris=relative_uris ) if self.checksum is not None: r["checksum"] = save( self.checksum, top=False, base_url=base_url, relative_uris=relative_uris ) if self.size is not None: r["size"] = save( self.size, top=False, base_url=base_url, relative_uris=relative_uris ) if self.secondaryFiles is not None: r["secondaryFiles"] = save( self.secondaryFiles, top=False, base_url=base_url, relative_uris=relative_uris, ) if self.format is not None: u = save_relative_uri(self.format, base_url, True, None, relative_uris) r["format"] = u if self.contents is not None: r["contents"] = save( self.contents, top=False, base_url=base_url, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset( [ "class", "location", "path", "basename", "dirname", "nameroot", "nameext", "checksum", "size", "secondaryFiles", "format", "contents", ] ) class Directory(Saveable): """ Represents a directory to present to a command line tool. Directories are represented as objects with `class` of `Directory`. Directory objects have a number of properties that provide metadata about the directory. The `location` property of a Directory is a URI that uniquely identifies the directory. Implementations must support the file:// URI scheme and may support other schemes such as http://. Alternately to `location`, implementations must also accept the `path` property on Directory, which must be a filesystem path available on the same host as the CWL runner (for inputs) or the runtime environment of a command line tool execution (for command line tool outputs). A Directory object may have a `listing` field. This is a list of File and Directory objects that are contained in the Directory. For each entry in `listing`, the `basename` property defines the name of the File or Subdirectory when staged to disk. If `listing` is not provided, the implementation must have some way of fetching the Directory listing at runtime based on the `location` field. If a Directory does not have `location`, it is a Directory literal. A Directory literal must provide `listing`. Directory literals must be created on disk at runtime as needed. The resources in a Directory literal do not need to have any implied relationship in their `location`. For example, a Directory listing may contain two files located on different hosts. It is the responsibility of the runtime to ensure that those files are staged to disk appropriately. Secondary files associated with files in `listing` must also be staged to the same Directory. When executing a CommandLineTool, Directories must be recursively staged first and have local values of `path` assigend. Directory objects in CommandLineTool output must provide either a `location` URI or a `path` property in the context of the tool execution runtime (local to the compute node, or within the executing container). An ExpressionTool may forward file references from input to output by using the same value for `location`. Name conflicts (the same `basename` appearing multiple times in `listing` or in any entry in `secondaryFiles` in the listing) is a fatal error. """ def __init__( self, location: Optional[Any] = None, path: Optional[Any] = None, basename: Optional[Any] = None, listing: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.class_ = "Directory" self.location = location self.path = path self.basename = basename self.listing = listing def __eq__(self, other: Any) -> bool: if isinstance(other, Directory): return bool( self.class_ == other.class_ and self.location == other.location and self.path == other.path and self.basename == other.basename and self.listing == other.listing ) return False def __hash__(self) -> int: return hash( (self.class_, self.location, self.path, self.basename, self.listing) ) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "Directory": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("class") is None: raise ValidationException("missing required field `class`", None, []) class_ = load_field( _doc.get("class"), uri_Directory_classLoader_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("class") ) if class_ not in (cls.__name__, loadingOptions.vocab.get(cls.__name__)): raise ValidationException(f"tried `{cls.__name__}` but") except ValidationException as e: raise e location = None if "location" in _doc: try: location = load_field( _doc.get("location"), uri_union_of_None_type_or_strtype_False_False_None_None, baseuri, loadingOptions, lc=_doc.get("location") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `location`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("location") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `location` field is not valid because:", SourceLine(_doc, "location", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `location` field is not valid because:", SourceLine(_doc, "location", str), [e], detailed_message=f"the `location` field with value `{val}` " "is not valid because:", ) ) path = None if "path" in _doc: try: path = load_field( _doc.get("path"), uri_union_of_None_type_or_strtype_False_False_None_None, baseuri, loadingOptions, lc=_doc.get("path") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `path`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("path") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `path` field is not valid because:", SourceLine(_doc, "path", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `path` field is not valid because:", SourceLine(_doc, "path", str), [e], detailed_message=f"the `path` field with value `{val}` " "is not valid because:", ) ) basename = None if "basename" in _doc: try: basename = load_field( _doc.get("basename"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("basename") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `basename`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("basename") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `basename` field is not valid because:", SourceLine(_doc, "basename", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `basename` field is not valid because:", SourceLine(_doc, "basename", str), [e], detailed_message=f"the `basename` field with value `{val}` " "is not valid because:", ) ) listing = None if "listing" in _doc: try: listing = load_field( _doc.get("listing"), union_of_None_type_or_array_of_union_of_FileLoader_or_DirectoryLoader, baseuri, loadingOptions, lc=_doc.get("listing") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `listing`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("listing") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `listing` field is not valid because:", SourceLine(_doc, "listing", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `listing` field is not valid because:", SourceLine(_doc, "listing", str), [e], detailed_message=f"the `listing` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `class`, `location`, `path`, `basename`, `listing`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( location=location, path=path, basename=basename, listing=listing, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.class_ is not None: uri = self.loadingOptions.vocab[self.class_] if p := self.loadingOptions.rvocab.get(uri[: -len(self.class_)]): uri = f"{p}:{self.class_}" else: uri = self.class_ u = save_relative_uri(uri, base_url, False, None, relative_uris) r["class"] = u if self.location is not None: u = save_relative_uri(self.location, base_url, False, None, relative_uris) r["location"] = u if self.path is not None: u = save_relative_uri(self.path, base_url, False, None, relative_uris) r["path"] = u if self.basename is not None: r["basename"] = save( self.basename, top=False, base_url=base_url, relative_uris=relative_uris ) if self.listing is not None: r["listing"] = save( self.listing, top=False, base_url=base_url, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["class", "location", "path", "basename", "listing"]) class SchemaBase(Saveable): pass class Parameter(SchemaBase): """ Define an input or output parameter to a process. """ pass class InputBinding(Saveable): pass class OutputBinding(Saveable): pass class InputSchema(SchemaBase): pass class OutputSchema(SchemaBase): pass class InputRecordField(CWLRecordField): name: str def __init__( self, name: Any, type_: Any, doc: Optional[Any] = None, inputBinding: Optional[Any] = None, label: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.doc = doc self.name = name if name is not None else "_:" + str(_uuid__.uuid4()) self.type_ = type_ self.inputBinding = inputBinding self.label = label def __eq__(self, other: Any) -> bool: if isinstance(other, InputRecordField): return bool( self.doc == other.doc and self.name == other.name and self.type_ == other.type_ and self.inputBinding == other.inputBinding and self.label == other.label ) return False def __hash__(self) -> int: return hash((self.doc, self.name, self.type_, self.inputBinding, self.label)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "InputRecordField": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] name = None if "name" in _doc: try: name = load_field( _doc.get("name"), uri_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("name") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `name`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("name") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [e], detailed_message=f"the `name` field with value `{val}` " "is not valid because:", ) ) __original_name_is_none = name is None if name is None: if docRoot is not None: name = docRoot else: _errors__.append(ValidationException("missing name")) if not __original_name_is_none: baseuri = cast(str, name) doc = None if "doc" in _doc: try: doc = load_field( _doc.get("doc"), union_of_None_type_or_strtype_or_array_of_strtype, baseuri, loadingOptions, lc=_doc.get("doc") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `doc`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("doc") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [e], detailed_message=f"the `doc` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("type") is None: raise ValidationException("missing required field `type`", None, []) type_ = load_field( _doc.get("type"), typedsl_union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype_2, baseuri, loadingOptions, lc=_doc.get("type") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `type`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("type") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [e], detailed_message=f"the `type` field with value `{val}` " "is not valid because:", ) ) inputBinding = None if "inputBinding" in _doc: try: inputBinding = load_field( _doc.get("inputBinding"), union_of_None_type_or_CommandLineBindingLoader, baseuri, loadingOptions, lc=_doc.get("inputBinding") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `inputBinding`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("inputBinding") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `inputBinding` field is not valid because:", SourceLine(_doc, "inputBinding", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `inputBinding` field is not valid because:", SourceLine(_doc, "inputBinding", str), [e], detailed_message=f"the `inputBinding` field with value `{val}` " "is not valid because:", ) ) label = None if "label" in _doc: try: label = load_field( _doc.get("label"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("label") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `label`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("label") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [e], detailed_message=f"the `label` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `doc`, `name`, `type`, `inputBinding`, `label`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( doc=doc, name=name, type_=type_, inputBinding=inputBinding, label=label, extension_fields=extension_fields, loadingOptions=loadingOptions, ) loadingOptions.idx[cast(str, name)] = (_constructed, loadingOptions) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.name is not None: u = save_relative_uri(self.name, base_url, True, None, relative_uris) r["name"] = u if self.doc is not None: r["doc"] = save( self.doc, top=False, base_url=self.name, relative_uris=relative_uris ) if self.type_ is not None: r["type"] = save( self.type_, top=False, base_url=self.name, relative_uris=relative_uris ) if self.inputBinding is not None: r["inputBinding"] = save( self.inputBinding, top=False, base_url=self.name, relative_uris=relative_uris, ) if self.label is not None: r["label"] = save( self.label, top=False, base_url=self.name, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["doc", "name", "type", "inputBinding", "label"]) class InputRecordSchema(CWLRecordSchema, InputSchema): name: str def __init__( self, type_: Any, fields: Optional[Any] = None, label: Optional[Any] = None, name: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.fields = fields self.type_ = type_ self.label = label self.name = name if name is not None else "_:" + str(_uuid__.uuid4()) def __eq__(self, other: Any) -> bool: if isinstance(other, InputRecordSchema): return bool( self.fields == other.fields and self.type_ == other.type_ and self.label == other.label and self.name == other.name ) return False def __hash__(self) -> int: return hash((self.fields, self.type_, self.label, self.name)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "InputRecordSchema": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] name = None if "name" in _doc: try: name = load_field( _doc.get("name"), uri_union_of_None_type_or_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("name") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `name`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("name") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [e], detailed_message=f"the `name` field with value `{val}` " "is not valid because:", ) ) __original_name_is_none = name is None if name is None: if docRoot is not None: name = docRoot else: name = "_:" + str(_uuid__.uuid4()) if not __original_name_is_none: baseuri = cast(str, name) fields = None if "fields" in _doc: try: fields = load_field( _doc.get("fields"), idmap_fields_union_of_None_type_or_array_of_InputRecordFieldLoader, baseuri, loadingOptions, lc=_doc.get("fields") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `fields`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("fields") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `fields` field is not valid because:", SourceLine(_doc, "fields", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `fields` field is not valid because:", SourceLine(_doc, "fields", str), [e], detailed_message=f"the `fields` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("type") is None: raise ValidationException("missing required field `type`", None, []) type_ = load_field( _doc.get("type"), typedsl_Record_nameLoader_2, baseuri, loadingOptions, lc=_doc.get("type") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `type`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("type") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [e], detailed_message=f"the `type` field with value `{val}` " "is not valid because:", ) ) label = None if "label" in _doc: try: label = load_field( _doc.get("label"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("label") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `label`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("label") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [e], detailed_message=f"the `label` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `fields`, `type`, `label`, `name`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( fields=fields, type_=type_, label=label, name=name, extension_fields=extension_fields, loadingOptions=loadingOptions, ) loadingOptions.idx[cast(str, name)] = (_constructed, loadingOptions) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.name is not None: u = save_relative_uri(self.name, base_url, True, None, relative_uris) r["name"] = u if self.fields is not None: r["fields"] = save( self.fields, top=False, base_url=self.name, relative_uris=relative_uris ) if self.type_ is not None: r["type"] = save( self.type_, top=False, base_url=self.name, relative_uris=relative_uris ) if self.label is not None: r["label"] = save( self.label, top=False, base_url=self.name, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["fields", "type", "label", "name"]) class InputEnumSchema(EnumSchema, InputSchema): name: str def __init__( self, symbols: Any, type_: Any, name: Optional[Any] = None, label: Optional[Any] = None, inputBinding: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.name = name if name is not None else "_:" + str(_uuid__.uuid4()) self.symbols = symbols self.type_ = type_ self.label = label self.inputBinding = inputBinding def __eq__(self, other: Any) -> bool: if isinstance(other, InputEnumSchema): return bool( self.name == other.name and self.symbols == other.symbols and self.type_ == other.type_ and self.label == other.label and self.inputBinding == other.inputBinding ) return False def __hash__(self) -> int: return hash( (self.name, self.symbols, self.type_, self.label, self.inputBinding) ) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "InputEnumSchema": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] name = None if "name" in _doc: try: name = load_field( _doc.get("name"), uri_union_of_None_type_or_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("name") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `name`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("name") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [e], detailed_message=f"the `name` field with value `{val}` " "is not valid because:", ) ) __original_name_is_none = name is None if name is None: if docRoot is not None: name = docRoot else: name = "_:" + str(_uuid__.uuid4()) if not __original_name_is_none: baseuri = cast(str, name) try: if _doc.get("symbols") is None: raise ValidationException("missing required field `symbols`", None, []) symbols = load_field( _doc.get("symbols"), uri_array_of_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("symbols") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `symbols`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("symbols") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `symbols` field is not valid because:", SourceLine(_doc, "symbols", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `symbols` field is not valid because:", SourceLine(_doc, "symbols", str), [e], detailed_message=f"the `symbols` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("type") is None: raise ValidationException("missing required field `type`", None, []) type_ = load_field( _doc.get("type"), typedsl_Enum_nameLoader_2, baseuri, loadingOptions, lc=_doc.get("type") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `type`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("type") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [e], detailed_message=f"the `type` field with value `{val}` " "is not valid because:", ) ) label = None if "label" in _doc: try: label = load_field( _doc.get("label"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("label") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `label`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("label") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [e], detailed_message=f"the `label` field with value `{val}` " "is not valid because:", ) ) inputBinding = None if "inputBinding" in _doc: try: inputBinding = load_field( _doc.get("inputBinding"), union_of_None_type_or_CommandLineBindingLoader, baseuri, loadingOptions, lc=_doc.get("inputBinding") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `inputBinding`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("inputBinding") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `inputBinding` field is not valid because:", SourceLine(_doc, "inputBinding", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `inputBinding` field is not valid because:", SourceLine(_doc, "inputBinding", str), [e], detailed_message=f"the `inputBinding` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `name`, `symbols`, `type`, `label`, `inputBinding`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( name=name, symbols=symbols, type_=type_, label=label, inputBinding=inputBinding, extension_fields=extension_fields, loadingOptions=loadingOptions, ) loadingOptions.idx[cast(str, name)] = (_constructed, loadingOptions) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.name is not None: u = save_relative_uri(self.name, base_url, True, None, relative_uris) r["name"] = u if self.symbols is not None: u = save_relative_uri(self.symbols, self.name, True, None, relative_uris) r["symbols"] = u if self.type_ is not None: r["type"] = save( self.type_, top=False, base_url=self.name, relative_uris=relative_uris ) if self.label is not None: r["label"] = save( self.label, top=False, base_url=self.name, relative_uris=relative_uris ) if self.inputBinding is not None: r["inputBinding"] = save( self.inputBinding, top=False, base_url=self.name, relative_uris=relative_uris, ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["name", "symbols", "type", "label", "inputBinding"]) class InputArraySchema(CWLArraySchema, InputSchema): def __init__( self, items: Any, type_: Any, label: Optional[Any] = None, inputBinding: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.items = items self.type_ = type_ self.label = label self.inputBinding = inputBinding def __eq__(self, other: Any) -> bool: if isinstance(other, InputArraySchema): return bool( self.items == other.items and self.type_ == other.type_ and self.label == other.label and self.inputBinding == other.inputBinding ) return False def __hash__(self) -> int: return hash((self.items, self.type_, self.label, self.inputBinding)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "InputArraySchema": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("items") is None: raise ValidationException("missing required field `items`", None, []) items = load_field( _doc.get("items"), uri_union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype_False_True_2_None, baseuri, loadingOptions, lc=_doc.get("items") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `items`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("items") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `items` field is not valid because:", SourceLine(_doc, "items", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `items` field is not valid because:", SourceLine(_doc, "items", str), [e], detailed_message=f"the `items` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("type") is None: raise ValidationException("missing required field `type`", None, []) type_ = load_field( _doc.get("type"), typedsl_Array_nameLoader_2, baseuri, loadingOptions, lc=_doc.get("type") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `type`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("type") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [e], detailed_message=f"the `type` field with value `{val}` " "is not valid because:", ) ) label = None if "label" in _doc: try: label = load_field( _doc.get("label"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("label") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `label`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("label") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [e], detailed_message=f"the `label` field with value `{val}` " "is not valid because:", ) ) inputBinding = None if "inputBinding" in _doc: try: inputBinding = load_field( _doc.get("inputBinding"), union_of_None_type_or_CommandLineBindingLoader, baseuri, loadingOptions, lc=_doc.get("inputBinding") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `inputBinding`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("inputBinding") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `inputBinding` field is not valid because:", SourceLine(_doc, "inputBinding", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `inputBinding` field is not valid because:", SourceLine(_doc, "inputBinding", str), [e], detailed_message=f"the `inputBinding` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `items`, `type`, `label`, `inputBinding`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( items=items, type_=type_, label=label, inputBinding=inputBinding, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.items is not None: u = save_relative_uri(self.items, base_url, False, 2, relative_uris) r["items"] = u if self.type_ is not None: r["type"] = save( self.type_, top=False, base_url=base_url, relative_uris=relative_uris ) if self.label is not None: r["label"] = save( self.label, top=False, base_url=base_url, relative_uris=relative_uris ) if self.inputBinding is not None: r["inputBinding"] = save( self.inputBinding, top=False, base_url=base_url, relative_uris=relative_uris, ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["items", "type", "label", "inputBinding"]) class OutputRecordField(CWLRecordField): name: str def __init__( self, name: Any, type_: Any, doc: Optional[Any] = None, outputBinding: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.doc = doc self.name = name if name is not None else "_:" + str(_uuid__.uuid4()) self.type_ = type_ self.outputBinding = outputBinding def __eq__(self, other: Any) -> bool: if isinstance(other, OutputRecordField): return bool( self.doc == other.doc and self.name == other.name and self.type_ == other.type_ and self.outputBinding == other.outputBinding ) return False def __hash__(self) -> int: return hash((self.doc, self.name, self.type_, self.outputBinding)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "OutputRecordField": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] name = None if "name" in _doc: try: name = load_field( _doc.get("name"), uri_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("name") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `name`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("name") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [e], detailed_message=f"the `name` field with value `{val}` " "is not valid because:", ) ) __original_name_is_none = name is None if name is None: if docRoot is not None: name = docRoot else: _errors__.append(ValidationException("missing name")) if not __original_name_is_none: baseuri = cast(str, name) doc = None if "doc" in _doc: try: doc = load_field( _doc.get("doc"), union_of_None_type_or_strtype_or_array_of_strtype, baseuri, loadingOptions, lc=_doc.get("doc") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `doc`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("doc") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [e], detailed_message=f"the `doc` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("type") is None: raise ValidationException("missing required field `type`", None, []) type_ = load_field( _doc.get("type"), typedsl_union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype_2, baseuri, loadingOptions, lc=_doc.get("type") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `type`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("type") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [e], detailed_message=f"the `type` field with value `{val}` " "is not valid because:", ) ) outputBinding = None if "outputBinding" in _doc: try: outputBinding = load_field( _doc.get("outputBinding"), union_of_None_type_or_CommandOutputBindingLoader, baseuri, loadingOptions, lc=_doc.get("outputBinding") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `outputBinding`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("outputBinding") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `outputBinding` field is not valid because:", SourceLine(_doc, "outputBinding", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `outputBinding` field is not valid because:", SourceLine(_doc, "outputBinding", str), [e], detailed_message=f"the `outputBinding` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `doc`, `name`, `type`, `outputBinding`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( doc=doc, name=name, type_=type_, outputBinding=outputBinding, extension_fields=extension_fields, loadingOptions=loadingOptions, ) loadingOptions.idx[cast(str, name)] = (_constructed, loadingOptions) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.name is not None: u = save_relative_uri(self.name, base_url, True, None, relative_uris) r["name"] = u if self.doc is not None: r["doc"] = save( self.doc, top=False, base_url=self.name, relative_uris=relative_uris ) if self.type_ is not None: r["type"] = save( self.type_, top=False, base_url=self.name, relative_uris=relative_uris ) if self.outputBinding is not None: r["outputBinding"] = save( self.outputBinding, top=False, base_url=self.name, relative_uris=relative_uris, ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["doc", "name", "type", "outputBinding"]) class OutputRecordSchema(CWLRecordSchema, OutputSchema): def __init__( self, type_: Any, fields: Optional[Any] = None, label: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.fields = fields self.type_ = type_ self.label = label def __eq__(self, other: Any) -> bool: if isinstance(other, OutputRecordSchema): return bool( self.fields == other.fields and self.type_ == other.type_ and self.label == other.label ) return False def __hash__(self) -> int: return hash((self.fields, self.type_, self.label)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "OutputRecordSchema": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] fields = None if "fields" in _doc: try: fields = load_field( _doc.get("fields"), idmap_fields_union_of_None_type_or_array_of_OutputRecordFieldLoader, baseuri, loadingOptions, lc=_doc.get("fields") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `fields`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("fields") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `fields` field is not valid because:", SourceLine(_doc, "fields", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `fields` field is not valid because:", SourceLine(_doc, "fields", str), [e], detailed_message=f"the `fields` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("type") is None: raise ValidationException("missing required field `type`", None, []) type_ = load_field( _doc.get("type"), typedsl_Record_nameLoader_2, baseuri, loadingOptions, lc=_doc.get("type") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `type`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("type") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [e], detailed_message=f"the `type` field with value `{val}` " "is not valid because:", ) ) label = None if "label" in _doc: try: label = load_field( _doc.get("label"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("label") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `label`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("label") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [e], detailed_message=f"the `label` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `fields`, `type`, `label`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( fields=fields, type_=type_, label=label, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.fields is not None: r["fields"] = save( self.fields, top=False, base_url=base_url, relative_uris=relative_uris ) if self.type_ is not None: r["type"] = save( self.type_, top=False, base_url=base_url, relative_uris=relative_uris ) if self.label is not None: r["label"] = save( self.label, top=False, base_url=base_url, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["fields", "type", "label"]) class OutputEnumSchema(EnumSchema, OutputSchema): name: str def __init__( self, symbols: Any, type_: Any, name: Optional[Any] = None, label: Optional[Any] = None, outputBinding: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.name = name if name is not None else "_:" + str(_uuid__.uuid4()) self.symbols = symbols self.type_ = type_ self.label = label self.outputBinding = outputBinding def __eq__(self, other: Any) -> bool: if isinstance(other, OutputEnumSchema): return bool( self.name == other.name and self.symbols == other.symbols and self.type_ == other.type_ and self.label == other.label and self.outputBinding == other.outputBinding ) return False def __hash__(self) -> int: return hash( (self.name, self.symbols, self.type_, self.label, self.outputBinding) ) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "OutputEnumSchema": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] name = None if "name" in _doc: try: name = load_field( _doc.get("name"), uri_union_of_None_type_or_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("name") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `name`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("name") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [e], detailed_message=f"the `name` field with value `{val}` " "is not valid because:", ) ) __original_name_is_none = name is None if name is None: if docRoot is not None: name = docRoot else: name = "_:" + str(_uuid__.uuid4()) if not __original_name_is_none: baseuri = cast(str, name) try: if _doc.get("symbols") is None: raise ValidationException("missing required field `symbols`", None, []) symbols = load_field( _doc.get("symbols"), uri_array_of_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("symbols") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `symbols`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("symbols") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `symbols` field is not valid because:", SourceLine(_doc, "symbols", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `symbols` field is not valid because:", SourceLine(_doc, "symbols", str), [e], detailed_message=f"the `symbols` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("type") is None: raise ValidationException("missing required field `type`", None, []) type_ = load_field( _doc.get("type"), typedsl_Enum_nameLoader_2, baseuri, loadingOptions, lc=_doc.get("type") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `type`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("type") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [e], detailed_message=f"the `type` field with value `{val}` " "is not valid because:", ) ) label = None if "label" in _doc: try: label = load_field( _doc.get("label"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("label") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `label`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("label") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [e], detailed_message=f"the `label` field with value `{val}` " "is not valid because:", ) ) outputBinding = None if "outputBinding" in _doc: try: outputBinding = load_field( _doc.get("outputBinding"), union_of_None_type_or_CommandOutputBindingLoader, baseuri, loadingOptions, lc=_doc.get("outputBinding") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `outputBinding`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("outputBinding") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `outputBinding` field is not valid because:", SourceLine(_doc, "outputBinding", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `outputBinding` field is not valid because:", SourceLine(_doc, "outputBinding", str), [e], detailed_message=f"the `outputBinding` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `name`, `symbols`, `type`, `label`, `outputBinding`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( name=name, symbols=symbols, type_=type_, label=label, outputBinding=outputBinding, extension_fields=extension_fields, loadingOptions=loadingOptions, ) loadingOptions.idx[cast(str, name)] = (_constructed, loadingOptions) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.name is not None: u = save_relative_uri(self.name, base_url, True, None, relative_uris) r["name"] = u if self.symbols is not None: u = save_relative_uri(self.symbols, self.name, True, None, relative_uris) r["symbols"] = u if self.type_ is not None: r["type"] = save( self.type_, top=False, base_url=self.name, relative_uris=relative_uris ) if self.label is not None: r["label"] = save( self.label, top=False, base_url=self.name, relative_uris=relative_uris ) if self.outputBinding is not None: r["outputBinding"] = save( self.outputBinding, top=False, base_url=self.name, relative_uris=relative_uris, ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["name", "symbols", "type", "label", "outputBinding"]) class OutputArraySchema(CWLArraySchema, OutputSchema): def __init__( self, items: Any, type_: Any, label: Optional[Any] = None, outputBinding: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.items = items self.type_ = type_ self.label = label self.outputBinding = outputBinding def __eq__(self, other: Any) -> bool: if isinstance(other, OutputArraySchema): return bool( self.items == other.items and self.type_ == other.type_ and self.label == other.label and self.outputBinding == other.outputBinding ) return False def __hash__(self) -> int: return hash((self.items, self.type_, self.label, self.outputBinding)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "OutputArraySchema": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("items") is None: raise ValidationException("missing required field `items`", None, []) items = load_field( _doc.get("items"), uri_union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype_False_True_2_None, baseuri, loadingOptions, lc=_doc.get("items") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `items`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("items") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `items` field is not valid because:", SourceLine(_doc, "items", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `items` field is not valid because:", SourceLine(_doc, "items", str), [e], detailed_message=f"the `items` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("type") is None: raise ValidationException("missing required field `type`", None, []) type_ = load_field( _doc.get("type"), typedsl_Array_nameLoader_2, baseuri, loadingOptions, lc=_doc.get("type") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `type`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("type") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [e], detailed_message=f"the `type` field with value `{val}` " "is not valid because:", ) ) label = None if "label" in _doc: try: label = load_field( _doc.get("label"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("label") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `label`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("label") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [e], detailed_message=f"the `label` field with value `{val}` " "is not valid because:", ) ) outputBinding = None if "outputBinding" in _doc: try: outputBinding = load_field( _doc.get("outputBinding"), union_of_None_type_or_CommandOutputBindingLoader, baseuri, loadingOptions, lc=_doc.get("outputBinding") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `outputBinding`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("outputBinding") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `outputBinding` field is not valid because:", SourceLine(_doc, "outputBinding", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `outputBinding` field is not valid because:", SourceLine(_doc, "outputBinding", str), [e], detailed_message=f"the `outputBinding` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `items`, `type`, `label`, `outputBinding`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( items=items, type_=type_, label=label, outputBinding=outputBinding, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.items is not None: u = save_relative_uri(self.items, base_url, False, 2, relative_uris) r["items"] = u if self.type_ is not None: r["type"] = save( self.type_, top=False, base_url=base_url, relative_uris=relative_uris ) if self.label is not None: r["label"] = save( self.label, top=False, base_url=base_url, relative_uris=relative_uris ) if self.outputBinding is not None: r["outputBinding"] = save( self.outputBinding, top=False, base_url=base_url, relative_uris=relative_uris, ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["items", "type", "label", "outputBinding"]) class InputParameter(Parameter): id: str def __init__( self, id: Any, label: Optional[Any] = None, secondaryFiles: Optional[Any] = None, streamable: Optional[Any] = None, doc: Optional[Any] = None, format: Optional[Any] = None, inputBinding: Optional[Any] = None, default: Optional[Any] = None, type_: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.label = label self.secondaryFiles = secondaryFiles self.streamable = streamable self.doc = doc self.id = id if id is not None else "_:" + str(_uuid__.uuid4()) self.format = format self.inputBinding = inputBinding self.default = default self.type_ = type_ def __eq__(self, other: Any) -> bool: if isinstance(other, InputParameter): return bool( self.label == other.label and self.secondaryFiles == other.secondaryFiles and self.streamable == other.streamable and self.doc == other.doc and self.id == other.id and self.format == other.format and self.inputBinding == other.inputBinding and self.default == other.default and self.type_ == other.type_ ) return False def __hash__(self) -> int: return hash( ( self.label, self.secondaryFiles, self.streamable, self.doc, self.id, self.format, self.inputBinding, self.default, self.type_, ) ) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "InputParameter": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] id = None if "id" in _doc: try: id = load_field( _doc.get("id"), uri_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("id") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `id`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("id") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `id` field is not valid because:", SourceLine(_doc, "id", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `id` field is not valid because:", SourceLine(_doc, "id", str), [e], detailed_message=f"the `id` field with value `{val}` " "is not valid because:", ) ) __original_id_is_none = id is None if id is None: if docRoot is not None: id = docRoot else: _errors__.append(ValidationException("missing id")) if not __original_id_is_none: baseuri = cast(str, id) label = None if "label" in _doc: try: label = load_field( _doc.get("label"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("label") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `label`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("label") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [e], detailed_message=f"the `label` field with value `{val}` " "is not valid because:", ) ) secondaryFiles = None if "secondaryFiles" in _doc: try: secondaryFiles = load_field( _doc.get("secondaryFiles"), union_of_None_type_or_strtype_or_ExpressionLoader_or_array_of_union_of_strtype_or_ExpressionLoader, baseuri, loadingOptions, lc=_doc.get("secondaryFiles") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `secondaryFiles`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("secondaryFiles") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `secondaryFiles` field is not valid because:", SourceLine(_doc, "secondaryFiles", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `secondaryFiles` field is not valid because:", SourceLine(_doc, "secondaryFiles", str), [e], detailed_message=f"the `secondaryFiles` field with value `{val}` " "is not valid because:", ) ) streamable = None if "streamable" in _doc: try: streamable = load_field( _doc.get("streamable"), union_of_None_type_or_booltype, baseuri, loadingOptions, lc=_doc.get("streamable") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `streamable`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("streamable") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `streamable` field is not valid because:", SourceLine(_doc, "streamable", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `streamable` field is not valid because:", SourceLine(_doc, "streamable", str), [e], detailed_message=f"the `streamable` field with value `{val}` " "is not valid because:", ) ) doc = None if "doc" in _doc: try: doc = load_field( _doc.get("doc"), union_of_None_type_or_strtype_or_array_of_strtype, baseuri, loadingOptions, lc=_doc.get("doc") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `doc`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("doc") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [e], detailed_message=f"the `doc` field with value `{val}` " "is not valid because:", ) ) format = None if "format" in _doc: try: format = load_field( _doc.get("format"), uri_union_of_None_type_or_strtype_or_array_of_strtype_or_ExpressionLoader_True_False_None_True, baseuri, loadingOptions, lc=_doc.get("format") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `format`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("format") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `format` field is not valid because:", SourceLine(_doc, "format", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `format` field is not valid because:", SourceLine(_doc, "format", str), [e], detailed_message=f"the `format` field with value `{val}` " "is not valid because:", ) ) inputBinding = None if "inputBinding" in _doc: try: inputBinding = load_field( _doc.get("inputBinding"), union_of_None_type_or_CommandLineBindingLoader, baseuri, loadingOptions, lc=_doc.get("inputBinding") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `inputBinding`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("inputBinding") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `inputBinding` field is not valid because:", SourceLine(_doc, "inputBinding", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `inputBinding` field is not valid because:", SourceLine(_doc, "inputBinding", str), [e], detailed_message=f"the `inputBinding` field with value `{val}` " "is not valid because:", ) ) default = None if "default" in _doc: try: default = load_field( _doc.get("default"), union_of_None_type_or_CWLObjectTypeLoader, baseuri, loadingOptions, lc=_doc.get("default") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `default`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("default") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `default` field is not valid because:", SourceLine(_doc, "default", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `default` field is not valid because:", SourceLine(_doc, "default", str), [e], detailed_message=f"the `default` field with value `{val}` " "is not valid because:", ) ) type_ = None if "type" in _doc: try: type_ = load_field( _doc.get("type"), typedsl_union_of_None_type_or_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype_2, baseuri, loadingOptions, lc=_doc.get("type") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `type`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("type") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [e], detailed_message=f"the `type` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `label`, `secondaryFiles`, `streamable`, `doc`, `id`, `format`, `inputBinding`, `default`, `type`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( label=label, secondaryFiles=secondaryFiles, streamable=streamable, doc=doc, id=id, format=format, inputBinding=inputBinding, default=default, type_=type_, extension_fields=extension_fields, loadingOptions=loadingOptions, ) loadingOptions.idx[cast(str, id)] = (_constructed, loadingOptions) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.id is not None: u = save_relative_uri(self.id, base_url, True, None, relative_uris) r["id"] = u if self.label is not None: r["label"] = save( self.label, top=False, base_url=self.id, relative_uris=relative_uris ) if self.secondaryFiles is not None: r["secondaryFiles"] = save( self.secondaryFiles, top=False, base_url=self.id, relative_uris=relative_uris, ) if self.streamable is not None: r["streamable"] = save( self.streamable, top=False, base_url=self.id, relative_uris=relative_uris, ) if self.doc is not None: r["doc"] = save( self.doc, top=False, base_url=self.id, relative_uris=relative_uris ) if self.format is not None: u = save_relative_uri(self.format, self.id, True, None, relative_uris) r["format"] = u if self.inputBinding is not None: r["inputBinding"] = save( self.inputBinding, top=False, base_url=self.id, relative_uris=relative_uris, ) if self.default is not None: r["default"] = save( self.default, top=False, base_url=self.id, relative_uris=relative_uris ) if self.type_ is not None: r["type"] = save( self.type_, top=False, base_url=self.id, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset( [ "label", "secondaryFiles", "streamable", "doc", "id", "format", "inputBinding", "default", "type", ] ) class OutputParameter(Parameter): id: str def __init__( self, id: Any, label: Optional[Any] = None, secondaryFiles: Optional[Any] = None, streamable: Optional[Any] = None, doc: Optional[Any] = None, outputBinding: Optional[Any] = None, format: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.label = label self.secondaryFiles = secondaryFiles self.streamable = streamable self.doc = doc self.id = id if id is not None else "_:" + str(_uuid__.uuid4()) self.outputBinding = outputBinding self.format = format def __eq__(self, other: Any) -> bool: if isinstance(other, OutputParameter): return bool( self.label == other.label and self.secondaryFiles == other.secondaryFiles and self.streamable == other.streamable and self.doc == other.doc and self.id == other.id and self.outputBinding == other.outputBinding and self.format == other.format ) return False def __hash__(self) -> int: return hash( ( self.label, self.secondaryFiles, self.streamable, self.doc, self.id, self.outputBinding, self.format, ) ) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "OutputParameter": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] id = None if "id" in _doc: try: id = load_field( _doc.get("id"), uri_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("id") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `id`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("id") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `id` field is not valid because:", SourceLine(_doc, "id", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `id` field is not valid because:", SourceLine(_doc, "id", str), [e], detailed_message=f"the `id` field with value `{val}` " "is not valid because:", ) ) __original_id_is_none = id is None if id is None: if docRoot is not None: id = docRoot else: _errors__.append(ValidationException("missing id")) if not __original_id_is_none: baseuri = cast(str, id) label = None if "label" in _doc: try: label = load_field( _doc.get("label"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("label") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `label`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("label") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [e], detailed_message=f"the `label` field with value `{val}` " "is not valid because:", ) ) secondaryFiles = None if "secondaryFiles" in _doc: try: secondaryFiles = load_field( _doc.get("secondaryFiles"), union_of_None_type_or_strtype_or_ExpressionLoader_or_array_of_union_of_strtype_or_ExpressionLoader, baseuri, loadingOptions, lc=_doc.get("secondaryFiles") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `secondaryFiles`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("secondaryFiles") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `secondaryFiles` field is not valid because:", SourceLine(_doc, "secondaryFiles", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `secondaryFiles` field is not valid because:", SourceLine(_doc, "secondaryFiles", str), [e], detailed_message=f"the `secondaryFiles` field with value `{val}` " "is not valid because:", ) ) streamable = None if "streamable" in _doc: try: streamable = load_field( _doc.get("streamable"), union_of_None_type_or_booltype, baseuri, loadingOptions, lc=_doc.get("streamable") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `streamable`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("streamable") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `streamable` field is not valid because:", SourceLine(_doc, "streamable", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `streamable` field is not valid because:", SourceLine(_doc, "streamable", str), [e], detailed_message=f"the `streamable` field with value `{val}` " "is not valid because:", ) ) doc = None if "doc" in _doc: try: doc = load_field( _doc.get("doc"), union_of_None_type_or_strtype_or_array_of_strtype, baseuri, loadingOptions, lc=_doc.get("doc") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `doc`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("doc") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [e], detailed_message=f"the `doc` field with value `{val}` " "is not valid because:", ) ) outputBinding = None if "outputBinding" in _doc: try: outputBinding = load_field( _doc.get("outputBinding"), union_of_None_type_or_CommandOutputBindingLoader, baseuri, loadingOptions, lc=_doc.get("outputBinding") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `outputBinding`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("outputBinding") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `outputBinding` field is not valid because:", SourceLine(_doc, "outputBinding", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `outputBinding` field is not valid because:", SourceLine(_doc, "outputBinding", str), [e], detailed_message=f"the `outputBinding` field with value `{val}` " "is not valid because:", ) ) format = None if "format" in _doc: try: format = load_field( _doc.get("format"), uri_union_of_None_type_or_strtype_or_ExpressionLoader_True_False_None_True, baseuri, loadingOptions, lc=_doc.get("format") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `format`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("format") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `format` field is not valid because:", SourceLine(_doc, "format", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `format` field is not valid because:", SourceLine(_doc, "format", str), [e], detailed_message=f"the `format` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `label`, `secondaryFiles`, `streamable`, `doc`, `id`, `outputBinding`, `format`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( label=label, secondaryFiles=secondaryFiles, streamable=streamable, doc=doc, id=id, outputBinding=outputBinding, format=format, extension_fields=extension_fields, loadingOptions=loadingOptions, ) loadingOptions.idx[cast(str, id)] = (_constructed, loadingOptions) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.id is not None: u = save_relative_uri(self.id, base_url, True, None, relative_uris) r["id"] = u if self.label is not None: r["label"] = save( self.label, top=False, base_url=self.id, relative_uris=relative_uris ) if self.secondaryFiles is not None: r["secondaryFiles"] = save( self.secondaryFiles, top=False, base_url=self.id, relative_uris=relative_uris, ) if self.streamable is not None: r["streamable"] = save( self.streamable, top=False, base_url=self.id, relative_uris=relative_uris, ) if self.doc is not None: r["doc"] = save( self.doc, top=False, base_url=self.id, relative_uris=relative_uris ) if self.outputBinding is not None: r["outputBinding"] = save( self.outputBinding, top=False, base_url=self.id, relative_uris=relative_uris, ) if self.format is not None: u = save_relative_uri(self.format, self.id, True, None, relative_uris) r["format"] = u # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset( [ "label", "secondaryFiles", "streamable", "doc", "id", "outputBinding", "format", ] ) class ProcessRequirement(Saveable): """ A process requirement declares a prerequisite that may or must be fulfilled before executing a process. See [`Process.hints`](#process) and [`Process.requirements`](#process). Process requirements are the primary mechanism for specifying extensions to the CWL core specification. """ pass class Process(Saveable): """ The base executable type in CWL is the `Process` object defined by the document. Note that the `Process` object is abstract and cannot be directly executed. """ pass class InlineJavascriptRequirement(ProcessRequirement): """ Indicates that the workflow platform must support inline Javascript expressions. If this requirement is not present, the workflow platform must not perform expression interpolatation. """ def __init__( self, expressionLib: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.class_ = "InlineJavascriptRequirement" self.expressionLib = expressionLib def __eq__(self, other: Any) -> bool: if isinstance(other, InlineJavascriptRequirement): return bool( self.class_ == other.class_ and self.expressionLib == other.expressionLib ) return False def __hash__(self) -> int: return hash((self.class_, self.expressionLib)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "InlineJavascriptRequirement": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("class") is None: raise ValidationException("missing required field `class`", None, []) class_ = load_field( _doc.get("class"), uri_InlineJavascriptRequirement_classLoader_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("class") ) if class_ not in (cls.__name__, loadingOptions.vocab.get(cls.__name__)): raise ValidationException(f"tried `{cls.__name__}` but") except ValidationException as e: raise e expressionLib = None if "expressionLib" in _doc: try: expressionLib = load_field( _doc.get("expressionLib"), union_of_None_type_or_array_of_strtype, baseuri, loadingOptions, lc=_doc.get("expressionLib") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `expressionLib`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("expressionLib") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `expressionLib` field is not valid because:", SourceLine(_doc, "expressionLib", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `expressionLib` field is not valid because:", SourceLine(_doc, "expressionLib", str), [e], detailed_message=f"the `expressionLib` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `class`, `expressionLib`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( expressionLib=expressionLib, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.class_ is not None: uri = self.loadingOptions.vocab[self.class_] if p := self.loadingOptions.rvocab.get(uri[: -len(self.class_)]): uri = f"{p}:{self.class_}" else: uri = self.class_ u = save_relative_uri(uri, base_url, False, None, relative_uris) r["class"] = u if self.expressionLib is not None: r["expressionLib"] = save( self.expressionLib, top=False, base_url=base_url, relative_uris=relative_uris, ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["class", "expressionLib"]) class SchemaDefRequirement(ProcessRequirement): """ This field consists of an array of type definitions which must be used when interpreting the `inputs` and `outputs` fields. When a `type` field contain a IRI, the implementation must check if the type is defined in `schemaDefs` and use that definition. If the type is not found in `schemaDefs`, it is an error. The entries in `schemaDefs` must be processed in the order listed such that later schema definitions may refer to earlier schema definitions. """ def __init__( self, types: Any, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.class_ = "SchemaDefRequirement" self.types = types def __eq__(self, other: Any) -> bool: if isinstance(other, SchemaDefRequirement): return bool(self.class_ == other.class_ and self.types == other.types) return False def __hash__(self) -> int: return hash((self.class_, self.types)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "SchemaDefRequirement": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("class") is None: raise ValidationException("missing required field `class`", None, []) class_ = load_field( _doc.get("class"), uri_SchemaDefRequirement_classLoader_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("class") ) if class_ not in (cls.__name__, loadingOptions.vocab.get(cls.__name__)): raise ValidationException(f"tried `{cls.__name__}` but") except ValidationException as e: raise e try: if _doc.get("types") is None: raise ValidationException("missing required field `types`", None, []) types = load_field( _doc.get("types"), array_of_union_of_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader, baseuri, loadingOptions, lc=_doc.get("types") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `types`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("types") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `types` field is not valid because:", SourceLine(_doc, "types", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `types` field is not valid because:", SourceLine(_doc, "types", str), [e], detailed_message=f"the `types` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `class`, `types`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( types=types, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.class_ is not None: uri = self.loadingOptions.vocab[self.class_] if p := self.loadingOptions.rvocab.get(uri[: -len(self.class_)]): uri = f"{p}:{self.class_}" else: uri = self.class_ u = save_relative_uri(uri, base_url, False, None, relative_uris) r["class"] = u if self.types is not None: r["types"] = save( self.types, top=False, base_url=base_url, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["class", "types"]) class EnvironmentDef(Saveable): """ Define an environment variable that will be set in the runtime environment by the workflow platform when executing the command line tool. May be the result of executing an expression, such as getting a parameter from input. """ def __init__( self, envName: Any, envValue: Any, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.envName = envName self.envValue = envValue def __eq__(self, other: Any) -> bool: if isinstance(other, EnvironmentDef): return bool( self.envName == other.envName and self.envValue == other.envValue ) return False def __hash__(self) -> int: return hash((self.envName, self.envValue)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "EnvironmentDef": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("envName") is None: raise ValidationException("missing required field `envName`", None, []) envName = load_field( _doc.get("envName"), strtype, baseuri, loadingOptions, lc=_doc.get("envName") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `envName`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("envName") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `envName` field is not valid because:", SourceLine(_doc, "envName", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `envName` field is not valid because:", SourceLine(_doc, "envName", str), [e], detailed_message=f"the `envName` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("envValue") is None: raise ValidationException("missing required field `envValue`", None, []) envValue = load_field( _doc.get("envValue"), union_of_strtype_or_ExpressionLoader, baseuri, loadingOptions, lc=_doc.get("envValue") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `envValue`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("envValue") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `envValue` field is not valid because:", SourceLine(_doc, "envValue", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `envValue` field is not valid because:", SourceLine(_doc, "envValue", str), [e], detailed_message=f"the `envValue` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `envName`, `envValue`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( envName=envName, envValue=envValue, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.envName is not None: r["envName"] = save( self.envName, top=False, base_url=base_url, relative_uris=relative_uris ) if self.envValue is not None: r["envValue"] = save( self.envValue, top=False, base_url=base_url, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["envName", "envValue"]) class CommandLineBinding(InputBinding): """ When listed under `inputBinding` in the input schema, the term "value" refers to the the corresponding value in the input object. For binding objects listed in `CommandLineTool.arguments`, the term "value" refers to the effective value after evaluating `valueFrom`. The binding behavior when building the command line depends on the data type of the value. If there is a mismatch between the type described by the input schema and the effective value, such as resulting from an expression evaluation, an implementation must use the data type of the effective value. - **string**: Add `prefix` and the string to the command line. - **number**: Add `prefix` and decimal representation to command line. - **boolean**: If true, add `prefix` to the command line. If false, add nothing. - **File**: Add `prefix` and the value of [`File.path`](#File) to the command line. - **Directory**: Add `prefix` and the value of [`Directory.path`](#Directory) to the command line. - **array**: If `itemSeparator` is specified, add `prefix` and the join the array into a single string with `itemSeparator` separating the items. Otherwise first add `prefix`, then recursively process individual elements. If the array is empty, it does not add anything to command line. - **object**: Add `prefix` only, and recursively add object fields for which `inputBinding` is specified. - **null**: Add nothing. """ def __init__( self, loadContents: Optional[Any] = None, position: Optional[Any] = None, prefix: Optional[Any] = None, separate: Optional[Any] = None, itemSeparator: Optional[Any] = None, valueFrom: Optional[Any] = None, shellQuote: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.loadContents = loadContents self.position = position self.prefix = prefix self.separate = separate self.itemSeparator = itemSeparator self.valueFrom = valueFrom self.shellQuote = shellQuote def __eq__(self, other: Any) -> bool: if isinstance(other, CommandLineBinding): return bool( self.loadContents == other.loadContents and self.position == other.position and self.prefix == other.prefix and self.separate == other.separate and self.itemSeparator == other.itemSeparator and self.valueFrom == other.valueFrom and self.shellQuote == other.shellQuote ) return False def __hash__(self) -> int: return hash( ( self.loadContents, self.position, self.prefix, self.separate, self.itemSeparator, self.valueFrom, self.shellQuote, ) ) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "CommandLineBinding": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] loadContents = None if "loadContents" in _doc: try: loadContents = load_field( _doc.get("loadContents"), union_of_None_type_or_booltype, baseuri, loadingOptions, lc=_doc.get("loadContents") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `loadContents`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("loadContents") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `loadContents` field is not valid because:", SourceLine(_doc, "loadContents", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `loadContents` field is not valid because:", SourceLine(_doc, "loadContents", str), [e], detailed_message=f"the `loadContents` field with value `{val}` " "is not valid because:", ) ) position = None if "position" in _doc: try: position = load_field( _doc.get("position"), union_of_None_type_or_inttype, baseuri, loadingOptions, lc=_doc.get("position") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `position`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("position") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `position` field is not valid because:", SourceLine(_doc, "position", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `position` field is not valid because:", SourceLine(_doc, "position", str), [e], detailed_message=f"the `position` field with value `{val}` " "is not valid because:", ) ) prefix = None if "prefix" in _doc: try: prefix = load_field( _doc.get("prefix"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("prefix") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `prefix`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("prefix") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `prefix` field is not valid because:", SourceLine(_doc, "prefix", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `prefix` field is not valid because:", SourceLine(_doc, "prefix", str), [e], detailed_message=f"the `prefix` field with value `{val}` " "is not valid because:", ) ) separate = None if "separate" in _doc: try: separate = load_field( _doc.get("separate"), union_of_None_type_or_booltype, baseuri, loadingOptions, lc=_doc.get("separate") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `separate`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("separate") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `separate` field is not valid because:", SourceLine(_doc, "separate", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `separate` field is not valid because:", SourceLine(_doc, "separate", str), [e], detailed_message=f"the `separate` field with value `{val}` " "is not valid because:", ) ) itemSeparator = None if "itemSeparator" in _doc: try: itemSeparator = load_field( _doc.get("itemSeparator"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("itemSeparator") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `itemSeparator`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("itemSeparator") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `itemSeparator` field is not valid because:", SourceLine(_doc, "itemSeparator", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `itemSeparator` field is not valid because:", SourceLine(_doc, "itemSeparator", str), [e], detailed_message=f"the `itemSeparator` field with value `{val}` " "is not valid because:", ) ) valueFrom = None if "valueFrom" in _doc: try: valueFrom = load_field( _doc.get("valueFrom"), union_of_None_type_or_strtype_or_ExpressionLoader, baseuri, loadingOptions, lc=_doc.get("valueFrom") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `valueFrom`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("valueFrom") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `valueFrom` field is not valid because:", SourceLine(_doc, "valueFrom", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `valueFrom` field is not valid because:", SourceLine(_doc, "valueFrom", str), [e], detailed_message=f"the `valueFrom` field with value `{val}` " "is not valid because:", ) ) shellQuote = None if "shellQuote" in _doc: try: shellQuote = load_field( _doc.get("shellQuote"), union_of_None_type_or_booltype, baseuri, loadingOptions, lc=_doc.get("shellQuote") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `shellQuote`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("shellQuote") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `shellQuote` field is not valid because:", SourceLine(_doc, "shellQuote", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `shellQuote` field is not valid because:", SourceLine(_doc, "shellQuote", str), [e], detailed_message=f"the `shellQuote` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `loadContents`, `position`, `prefix`, `separate`, `itemSeparator`, `valueFrom`, `shellQuote`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( loadContents=loadContents, position=position, prefix=prefix, separate=separate, itemSeparator=itemSeparator, valueFrom=valueFrom, shellQuote=shellQuote, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.loadContents is not None: r["loadContents"] = save( self.loadContents, top=False, base_url=base_url, relative_uris=relative_uris, ) if self.position is not None: r["position"] = save( self.position, top=False, base_url=base_url, relative_uris=relative_uris ) if self.prefix is not None: r["prefix"] = save( self.prefix, top=False, base_url=base_url, relative_uris=relative_uris ) if self.separate is not None: r["separate"] = save( self.separate, top=False, base_url=base_url, relative_uris=relative_uris ) if self.itemSeparator is not None: r["itemSeparator"] = save( self.itemSeparator, top=False, base_url=base_url, relative_uris=relative_uris, ) if self.valueFrom is not None: r["valueFrom"] = save( self.valueFrom, top=False, base_url=base_url, relative_uris=relative_uris, ) if self.shellQuote is not None: r["shellQuote"] = save( self.shellQuote, top=False, base_url=base_url, relative_uris=relative_uris, ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset( [ "loadContents", "position", "prefix", "separate", "itemSeparator", "valueFrom", "shellQuote", ] ) class CommandOutputBinding(OutputBinding): """ Describes how to generate an output parameter based on the files produced by a CommandLineTool. The output parameter value is generated by applying these operations in the following order: - glob - loadContents - outputEval - secondaryFiles """ def __init__( self, glob: Optional[Any] = None, loadContents: Optional[Any] = None, outputEval: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.glob = glob self.loadContents = loadContents self.outputEval = outputEval def __eq__(self, other: Any) -> bool: if isinstance(other, CommandOutputBinding): return bool( self.glob == other.glob and self.loadContents == other.loadContents and self.outputEval == other.outputEval ) return False def __hash__(self) -> int: return hash((self.glob, self.loadContents, self.outputEval)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "CommandOutputBinding": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] glob = None if "glob" in _doc: try: glob = load_field( _doc.get("glob"), union_of_None_type_or_strtype_or_ExpressionLoader_or_array_of_strtype, baseuri, loadingOptions, lc=_doc.get("glob") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `glob`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("glob") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `glob` field is not valid because:", SourceLine(_doc, "glob", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `glob` field is not valid because:", SourceLine(_doc, "glob", str), [e], detailed_message=f"the `glob` field with value `{val}` " "is not valid because:", ) ) loadContents = None if "loadContents" in _doc: try: loadContents = load_field( _doc.get("loadContents"), union_of_None_type_or_booltype, baseuri, loadingOptions, lc=_doc.get("loadContents") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `loadContents`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("loadContents") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `loadContents` field is not valid because:", SourceLine(_doc, "loadContents", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `loadContents` field is not valid because:", SourceLine(_doc, "loadContents", str), [e], detailed_message=f"the `loadContents` field with value `{val}` " "is not valid because:", ) ) outputEval = None if "outputEval" in _doc: try: outputEval = load_field( _doc.get("outputEval"), union_of_None_type_or_strtype_or_ExpressionLoader, baseuri, loadingOptions, lc=_doc.get("outputEval") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `outputEval`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("outputEval") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `outputEval` field is not valid because:", SourceLine(_doc, "outputEval", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `outputEval` field is not valid because:", SourceLine(_doc, "outputEval", str), [e], detailed_message=f"the `outputEval` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `glob`, `loadContents`, `outputEval`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( glob=glob, loadContents=loadContents, outputEval=outputEval, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.glob is not None: r["glob"] = save( self.glob, top=False, base_url=base_url, relative_uris=relative_uris ) if self.loadContents is not None: r["loadContents"] = save( self.loadContents, top=False, base_url=base_url, relative_uris=relative_uris, ) if self.outputEval is not None: r["outputEval"] = save( self.outputEval, top=False, base_url=base_url, relative_uris=relative_uris, ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["glob", "loadContents", "outputEval"]) class CommandInputRecordField(InputRecordField): name: str def __init__( self, name: Any, type_: Any, doc: Optional[Any] = None, inputBinding: Optional[Any] = None, label: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.doc = doc self.name = name if name is not None else "_:" + str(_uuid__.uuid4()) self.type_ = type_ self.inputBinding = inputBinding self.label = label def __eq__(self, other: Any) -> bool: if isinstance(other, CommandInputRecordField): return bool( self.doc == other.doc and self.name == other.name and self.type_ == other.type_ and self.inputBinding == other.inputBinding and self.label == other.label ) return False def __hash__(self) -> int: return hash((self.doc, self.name, self.type_, self.inputBinding, self.label)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "CommandInputRecordField": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] name = None if "name" in _doc: try: name = load_field( _doc.get("name"), uri_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("name") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `name`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("name") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [e], detailed_message=f"the `name` field with value `{val}` " "is not valid because:", ) ) __original_name_is_none = name is None if name is None: if docRoot is not None: name = docRoot else: _errors__.append(ValidationException("missing name")) if not __original_name_is_none: baseuri = cast(str, name) doc = None if "doc" in _doc: try: doc = load_field( _doc.get("doc"), union_of_None_type_or_strtype_or_array_of_strtype, baseuri, loadingOptions, lc=_doc.get("doc") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `doc`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("doc") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [e], detailed_message=f"the `doc` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("type") is None: raise ValidationException("missing required field `type`", None, []) type_ = load_field( _doc.get("type"), typedsl_union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype_2, baseuri, loadingOptions, lc=_doc.get("type") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `type`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("type") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [e], detailed_message=f"the `type` field with value `{val}` " "is not valid because:", ) ) inputBinding = None if "inputBinding" in _doc: try: inputBinding = load_field( _doc.get("inputBinding"), union_of_None_type_or_CommandLineBindingLoader, baseuri, loadingOptions, lc=_doc.get("inputBinding") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `inputBinding`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("inputBinding") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `inputBinding` field is not valid because:", SourceLine(_doc, "inputBinding", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `inputBinding` field is not valid because:", SourceLine(_doc, "inputBinding", str), [e], detailed_message=f"the `inputBinding` field with value `{val}` " "is not valid because:", ) ) label = None if "label" in _doc: try: label = load_field( _doc.get("label"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("label") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `label`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("label") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [e], detailed_message=f"the `label` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `doc`, `name`, `type`, `inputBinding`, `label`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( doc=doc, name=name, type_=type_, inputBinding=inputBinding, label=label, extension_fields=extension_fields, loadingOptions=loadingOptions, ) loadingOptions.idx[cast(str, name)] = (_constructed, loadingOptions) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.name is not None: u = save_relative_uri(self.name, base_url, True, None, relative_uris) r["name"] = u if self.doc is not None: r["doc"] = save( self.doc, top=False, base_url=self.name, relative_uris=relative_uris ) if self.type_ is not None: r["type"] = save( self.type_, top=False, base_url=self.name, relative_uris=relative_uris ) if self.inputBinding is not None: r["inputBinding"] = save( self.inputBinding, top=False, base_url=self.name, relative_uris=relative_uris, ) if self.label is not None: r["label"] = save( self.label, top=False, base_url=self.name, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["doc", "name", "type", "inputBinding", "label"]) class CommandInputRecordSchema(InputRecordSchema): name: str def __init__( self, type_: Any, fields: Optional[Any] = None, label: Optional[Any] = None, name: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.fields = fields self.type_ = type_ self.label = label self.name = name if name is not None else "_:" + str(_uuid__.uuid4()) def __eq__(self, other: Any) -> bool: if isinstance(other, CommandInputRecordSchema): return bool( self.fields == other.fields and self.type_ == other.type_ and self.label == other.label and self.name == other.name ) return False def __hash__(self) -> int: return hash((self.fields, self.type_, self.label, self.name)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "CommandInputRecordSchema": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] name = None if "name" in _doc: try: name = load_field( _doc.get("name"), uri_union_of_None_type_or_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("name") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `name`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("name") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [e], detailed_message=f"the `name` field with value `{val}` " "is not valid because:", ) ) __original_name_is_none = name is None if name is None: if docRoot is not None: name = docRoot else: name = "_:" + str(_uuid__.uuid4()) if not __original_name_is_none: baseuri = cast(str, name) fields = None if "fields" in _doc: try: fields = load_field( _doc.get("fields"), idmap_fields_union_of_None_type_or_array_of_CommandInputRecordFieldLoader, baseuri, loadingOptions, lc=_doc.get("fields") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `fields`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("fields") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `fields` field is not valid because:", SourceLine(_doc, "fields", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `fields` field is not valid because:", SourceLine(_doc, "fields", str), [e], detailed_message=f"the `fields` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("type") is None: raise ValidationException("missing required field `type`", None, []) type_ = load_field( _doc.get("type"), typedsl_Record_nameLoader_2, baseuri, loadingOptions, lc=_doc.get("type") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `type`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("type") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [e], detailed_message=f"the `type` field with value `{val}` " "is not valid because:", ) ) label = None if "label" in _doc: try: label = load_field( _doc.get("label"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("label") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `label`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("label") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [e], detailed_message=f"the `label` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `fields`, `type`, `label`, `name`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( fields=fields, type_=type_, label=label, name=name, extension_fields=extension_fields, loadingOptions=loadingOptions, ) loadingOptions.idx[cast(str, name)] = (_constructed, loadingOptions) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.name is not None: u = save_relative_uri(self.name, base_url, True, None, relative_uris) r["name"] = u if self.fields is not None: r["fields"] = save( self.fields, top=False, base_url=self.name, relative_uris=relative_uris ) if self.type_ is not None: r["type"] = save( self.type_, top=False, base_url=self.name, relative_uris=relative_uris ) if self.label is not None: r["label"] = save( self.label, top=False, base_url=self.name, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["fields", "type", "label", "name"]) class CommandInputEnumSchema(InputEnumSchema): name: str def __init__( self, symbols: Any, type_: Any, name: Optional[Any] = None, label: Optional[Any] = None, inputBinding: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.name = name if name is not None else "_:" + str(_uuid__.uuid4()) self.symbols = symbols self.type_ = type_ self.label = label self.inputBinding = inputBinding def __eq__(self, other: Any) -> bool: if isinstance(other, CommandInputEnumSchema): return bool( self.name == other.name and self.symbols == other.symbols and self.type_ == other.type_ and self.label == other.label and self.inputBinding == other.inputBinding ) return False def __hash__(self) -> int: return hash( (self.name, self.symbols, self.type_, self.label, self.inputBinding) ) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "CommandInputEnumSchema": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] name = None if "name" in _doc: try: name = load_field( _doc.get("name"), uri_union_of_None_type_or_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("name") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `name`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("name") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [e], detailed_message=f"the `name` field with value `{val}` " "is not valid because:", ) ) __original_name_is_none = name is None if name is None: if docRoot is not None: name = docRoot else: name = "_:" + str(_uuid__.uuid4()) if not __original_name_is_none: baseuri = cast(str, name) try: if _doc.get("symbols") is None: raise ValidationException("missing required field `symbols`", None, []) symbols = load_field( _doc.get("symbols"), uri_array_of_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("symbols") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `symbols`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("symbols") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `symbols` field is not valid because:", SourceLine(_doc, "symbols", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `symbols` field is not valid because:", SourceLine(_doc, "symbols", str), [e], detailed_message=f"the `symbols` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("type") is None: raise ValidationException("missing required field `type`", None, []) type_ = load_field( _doc.get("type"), typedsl_Enum_nameLoader_2, baseuri, loadingOptions, lc=_doc.get("type") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `type`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("type") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [e], detailed_message=f"the `type` field with value `{val}` " "is not valid because:", ) ) label = None if "label" in _doc: try: label = load_field( _doc.get("label"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("label") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `label`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("label") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [e], detailed_message=f"the `label` field with value `{val}` " "is not valid because:", ) ) inputBinding = None if "inputBinding" in _doc: try: inputBinding = load_field( _doc.get("inputBinding"), union_of_None_type_or_CommandLineBindingLoader, baseuri, loadingOptions, lc=_doc.get("inputBinding") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `inputBinding`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("inputBinding") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `inputBinding` field is not valid because:", SourceLine(_doc, "inputBinding", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `inputBinding` field is not valid because:", SourceLine(_doc, "inputBinding", str), [e], detailed_message=f"the `inputBinding` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `name`, `symbols`, `type`, `label`, `inputBinding`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( name=name, symbols=symbols, type_=type_, label=label, inputBinding=inputBinding, extension_fields=extension_fields, loadingOptions=loadingOptions, ) loadingOptions.idx[cast(str, name)] = (_constructed, loadingOptions) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.name is not None: u = save_relative_uri(self.name, base_url, True, None, relative_uris) r["name"] = u if self.symbols is not None: u = save_relative_uri(self.symbols, self.name, True, None, relative_uris) r["symbols"] = u if self.type_ is not None: r["type"] = save( self.type_, top=False, base_url=self.name, relative_uris=relative_uris ) if self.label is not None: r["label"] = save( self.label, top=False, base_url=self.name, relative_uris=relative_uris ) if self.inputBinding is not None: r["inputBinding"] = save( self.inputBinding, top=False, base_url=self.name, relative_uris=relative_uris, ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["name", "symbols", "type", "label", "inputBinding"]) class CommandInputArraySchema(InputArraySchema): def __init__( self, items: Any, type_: Any, label: Optional[Any] = None, inputBinding: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.items = items self.type_ = type_ self.label = label self.inputBinding = inputBinding def __eq__(self, other: Any) -> bool: if isinstance(other, CommandInputArraySchema): return bool( self.items == other.items and self.type_ == other.type_ and self.label == other.label and self.inputBinding == other.inputBinding ) return False def __hash__(self) -> int: return hash((self.items, self.type_, self.label, self.inputBinding)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "CommandInputArraySchema": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("items") is None: raise ValidationException("missing required field `items`", None, []) items = load_field( _doc.get("items"), uri_union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype_False_True_2_None, baseuri, loadingOptions, lc=_doc.get("items") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `items`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("items") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `items` field is not valid because:", SourceLine(_doc, "items", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `items` field is not valid because:", SourceLine(_doc, "items", str), [e], detailed_message=f"the `items` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("type") is None: raise ValidationException("missing required field `type`", None, []) type_ = load_field( _doc.get("type"), typedsl_Array_nameLoader_2, baseuri, loadingOptions, lc=_doc.get("type") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `type`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("type") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [e], detailed_message=f"the `type` field with value `{val}` " "is not valid because:", ) ) label = None if "label" in _doc: try: label = load_field( _doc.get("label"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("label") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `label`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("label") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [e], detailed_message=f"the `label` field with value `{val}` " "is not valid because:", ) ) inputBinding = None if "inputBinding" in _doc: try: inputBinding = load_field( _doc.get("inputBinding"), union_of_None_type_or_CommandLineBindingLoader, baseuri, loadingOptions, lc=_doc.get("inputBinding") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `inputBinding`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("inputBinding") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `inputBinding` field is not valid because:", SourceLine(_doc, "inputBinding", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `inputBinding` field is not valid because:", SourceLine(_doc, "inputBinding", str), [e], detailed_message=f"the `inputBinding` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `items`, `type`, `label`, `inputBinding`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( items=items, type_=type_, label=label, inputBinding=inputBinding, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.items is not None: u = save_relative_uri(self.items, base_url, False, 2, relative_uris) r["items"] = u if self.type_ is not None: r["type"] = save( self.type_, top=False, base_url=base_url, relative_uris=relative_uris ) if self.label is not None: r["label"] = save( self.label, top=False, base_url=base_url, relative_uris=relative_uris ) if self.inputBinding is not None: r["inputBinding"] = save( self.inputBinding, top=False, base_url=base_url, relative_uris=relative_uris, ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["items", "type", "label", "inputBinding"]) class CommandOutputRecordField(OutputRecordField): name: str def __init__( self, name: Any, type_: Any, doc: Optional[Any] = None, outputBinding: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.doc = doc self.name = name if name is not None else "_:" + str(_uuid__.uuid4()) self.type_ = type_ self.outputBinding = outputBinding def __eq__(self, other: Any) -> bool: if isinstance(other, CommandOutputRecordField): return bool( self.doc == other.doc and self.name == other.name and self.type_ == other.type_ and self.outputBinding == other.outputBinding ) return False def __hash__(self) -> int: return hash((self.doc, self.name, self.type_, self.outputBinding)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "CommandOutputRecordField": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] name = None if "name" in _doc: try: name = load_field( _doc.get("name"), uri_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("name") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `name`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("name") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [e], detailed_message=f"the `name` field with value `{val}` " "is not valid because:", ) ) __original_name_is_none = name is None if name is None: if docRoot is not None: name = docRoot else: _errors__.append(ValidationException("missing name")) if not __original_name_is_none: baseuri = cast(str, name) doc = None if "doc" in _doc: try: doc = load_field( _doc.get("doc"), union_of_None_type_or_strtype_or_array_of_strtype, baseuri, loadingOptions, lc=_doc.get("doc") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `doc`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("doc") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [e], detailed_message=f"the `doc` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("type") is None: raise ValidationException("missing required field `type`", None, []) type_ = load_field( _doc.get("type"), typedsl_union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype_2, baseuri, loadingOptions, lc=_doc.get("type") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `type`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("type") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [e], detailed_message=f"the `type` field with value `{val}` " "is not valid because:", ) ) outputBinding = None if "outputBinding" in _doc: try: outputBinding = load_field( _doc.get("outputBinding"), union_of_None_type_or_CommandOutputBindingLoader, baseuri, loadingOptions, lc=_doc.get("outputBinding") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `outputBinding`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("outputBinding") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `outputBinding` field is not valid because:", SourceLine(_doc, "outputBinding", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `outputBinding` field is not valid because:", SourceLine(_doc, "outputBinding", str), [e], detailed_message=f"the `outputBinding` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `doc`, `name`, `type`, `outputBinding`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( doc=doc, name=name, type_=type_, outputBinding=outputBinding, extension_fields=extension_fields, loadingOptions=loadingOptions, ) loadingOptions.idx[cast(str, name)] = (_constructed, loadingOptions) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.name is not None: u = save_relative_uri(self.name, base_url, True, None, relative_uris) r["name"] = u if self.doc is not None: r["doc"] = save( self.doc, top=False, base_url=self.name, relative_uris=relative_uris ) if self.type_ is not None: r["type"] = save( self.type_, top=False, base_url=self.name, relative_uris=relative_uris ) if self.outputBinding is not None: r["outputBinding"] = save( self.outputBinding, top=False, base_url=self.name, relative_uris=relative_uris, ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["doc", "name", "type", "outputBinding"]) class CommandOutputRecordSchema(OutputRecordSchema): name: str def __init__( self, type_: Any, fields: Optional[Any] = None, label: Optional[Any] = None, name: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.fields = fields self.type_ = type_ self.label = label self.name = name if name is not None else "_:" + str(_uuid__.uuid4()) def __eq__(self, other: Any) -> bool: if isinstance(other, CommandOutputRecordSchema): return bool( self.fields == other.fields and self.type_ == other.type_ and self.label == other.label and self.name == other.name ) return False def __hash__(self) -> int: return hash((self.fields, self.type_, self.label, self.name)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "CommandOutputRecordSchema": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] name = None if "name" in _doc: try: name = load_field( _doc.get("name"), uri_union_of_None_type_or_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("name") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `name`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("name") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [e], detailed_message=f"the `name` field with value `{val}` " "is not valid because:", ) ) __original_name_is_none = name is None if name is None: if docRoot is not None: name = docRoot else: name = "_:" + str(_uuid__.uuid4()) if not __original_name_is_none: baseuri = cast(str, name) fields = None if "fields" in _doc: try: fields = load_field( _doc.get("fields"), idmap_fields_union_of_None_type_or_array_of_CommandOutputRecordFieldLoader, baseuri, loadingOptions, lc=_doc.get("fields") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `fields`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("fields") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `fields` field is not valid because:", SourceLine(_doc, "fields", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `fields` field is not valid because:", SourceLine(_doc, "fields", str), [e], detailed_message=f"the `fields` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("type") is None: raise ValidationException("missing required field `type`", None, []) type_ = load_field( _doc.get("type"), typedsl_Record_nameLoader_2, baseuri, loadingOptions, lc=_doc.get("type") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `type`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("type") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [e], detailed_message=f"the `type` field with value `{val}` " "is not valid because:", ) ) label = None if "label" in _doc: try: label = load_field( _doc.get("label"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("label") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `label`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("label") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [e], detailed_message=f"the `label` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `fields`, `type`, `label`, `name`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( fields=fields, type_=type_, label=label, name=name, extension_fields=extension_fields, loadingOptions=loadingOptions, ) loadingOptions.idx[cast(str, name)] = (_constructed, loadingOptions) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.name is not None: u = save_relative_uri(self.name, base_url, True, None, relative_uris) r["name"] = u if self.fields is not None: r["fields"] = save( self.fields, top=False, base_url=self.name, relative_uris=relative_uris ) if self.type_ is not None: r["type"] = save( self.type_, top=False, base_url=self.name, relative_uris=relative_uris ) if self.label is not None: r["label"] = save( self.label, top=False, base_url=self.name, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["fields", "type", "label", "name"]) class CommandOutputEnumSchema(OutputEnumSchema): name: str def __init__( self, symbols: Any, type_: Any, name: Optional[Any] = None, label: Optional[Any] = None, outputBinding: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.name = name if name is not None else "_:" + str(_uuid__.uuid4()) self.symbols = symbols self.type_ = type_ self.label = label self.outputBinding = outputBinding def __eq__(self, other: Any) -> bool: if isinstance(other, CommandOutputEnumSchema): return bool( self.name == other.name and self.symbols == other.symbols and self.type_ == other.type_ and self.label == other.label and self.outputBinding == other.outputBinding ) return False def __hash__(self) -> int: return hash( (self.name, self.symbols, self.type_, self.label, self.outputBinding) ) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "CommandOutputEnumSchema": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] name = None if "name" in _doc: try: name = load_field( _doc.get("name"), uri_union_of_None_type_or_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("name") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `name`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("name") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [e], detailed_message=f"the `name` field with value `{val}` " "is not valid because:", ) ) __original_name_is_none = name is None if name is None: if docRoot is not None: name = docRoot else: name = "_:" + str(_uuid__.uuid4()) if not __original_name_is_none: baseuri = cast(str, name) try: if _doc.get("symbols") is None: raise ValidationException("missing required field `symbols`", None, []) symbols = load_field( _doc.get("symbols"), uri_array_of_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("symbols") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `symbols`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("symbols") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `symbols` field is not valid because:", SourceLine(_doc, "symbols", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `symbols` field is not valid because:", SourceLine(_doc, "symbols", str), [e], detailed_message=f"the `symbols` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("type") is None: raise ValidationException("missing required field `type`", None, []) type_ = load_field( _doc.get("type"), typedsl_Enum_nameLoader_2, baseuri, loadingOptions, lc=_doc.get("type") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `type`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("type") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [e], detailed_message=f"the `type` field with value `{val}` " "is not valid because:", ) ) label = None if "label" in _doc: try: label = load_field( _doc.get("label"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("label") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `label`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("label") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [e], detailed_message=f"the `label` field with value `{val}` " "is not valid because:", ) ) outputBinding = None if "outputBinding" in _doc: try: outputBinding = load_field( _doc.get("outputBinding"), union_of_None_type_or_CommandOutputBindingLoader, baseuri, loadingOptions, lc=_doc.get("outputBinding") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `outputBinding`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("outputBinding") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `outputBinding` field is not valid because:", SourceLine(_doc, "outputBinding", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `outputBinding` field is not valid because:", SourceLine(_doc, "outputBinding", str), [e], detailed_message=f"the `outputBinding` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `name`, `symbols`, `type`, `label`, `outputBinding`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( name=name, symbols=symbols, type_=type_, label=label, outputBinding=outputBinding, extension_fields=extension_fields, loadingOptions=loadingOptions, ) loadingOptions.idx[cast(str, name)] = (_constructed, loadingOptions) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.name is not None: u = save_relative_uri(self.name, base_url, True, None, relative_uris) r["name"] = u if self.symbols is not None: u = save_relative_uri(self.symbols, self.name, True, None, relative_uris) r["symbols"] = u if self.type_ is not None: r["type"] = save( self.type_, top=False, base_url=self.name, relative_uris=relative_uris ) if self.label is not None: r["label"] = save( self.label, top=False, base_url=self.name, relative_uris=relative_uris ) if self.outputBinding is not None: r["outputBinding"] = save( self.outputBinding, top=False, base_url=self.name, relative_uris=relative_uris, ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["name", "symbols", "type", "label", "outputBinding"]) class CommandOutputArraySchema(OutputArraySchema): def __init__( self, items: Any, type_: Any, label: Optional[Any] = None, outputBinding: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.items = items self.type_ = type_ self.label = label self.outputBinding = outputBinding def __eq__(self, other: Any) -> bool: if isinstance(other, CommandOutputArraySchema): return bool( self.items == other.items and self.type_ == other.type_ and self.label == other.label and self.outputBinding == other.outputBinding ) return False def __hash__(self) -> int: return hash((self.items, self.type_, self.label, self.outputBinding)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "CommandOutputArraySchema": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("items") is None: raise ValidationException("missing required field `items`", None, []) items = load_field( _doc.get("items"), uri_union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype_False_True_2_None, baseuri, loadingOptions, lc=_doc.get("items") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `items`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("items") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `items` field is not valid because:", SourceLine(_doc, "items", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `items` field is not valid because:", SourceLine(_doc, "items", str), [e], detailed_message=f"the `items` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("type") is None: raise ValidationException("missing required field `type`", None, []) type_ = load_field( _doc.get("type"), typedsl_Array_nameLoader_2, baseuri, loadingOptions, lc=_doc.get("type") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `type`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("type") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [e], detailed_message=f"the `type` field with value `{val}` " "is not valid because:", ) ) label = None if "label" in _doc: try: label = load_field( _doc.get("label"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("label") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `label`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("label") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [e], detailed_message=f"the `label` field with value `{val}` " "is not valid because:", ) ) outputBinding = None if "outputBinding" in _doc: try: outputBinding = load_field( _doc.get("outputBinding"), union_of_None_type_or_CommandOutputBindingLoader, baseuri, loadingOptions, lc=_doc.get("outputBinding") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `outputBinding`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("outputBinding") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `outputBinding` field is not valid because:", SourceLine(_doc, "outputBinding", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `outputBinding` field is not valid because:", SourceLine(_doc, "outputBinding", str), [e], detailed_message=f"the `outputBinding` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `items`, `type`, `label`, `outputBinding`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( items=items, type_=type_, label=label, outputBinding=outputBinding, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.items is not None: u = save_relative_uri(self.items, base_url, False, 2, relative_uris) r["items"] = u if self.type_ is not None: r["type"] = save( self.type_, top=False, base_url=base_url, relative_uris=relative_uris ) if self.label is not None: r["label"] = save( self.label, top=False, base_url=base_url, relative_uris=relative_uris ) if self.outputBinding is not None: r["outputBinding"] = save( self.outputBinding, top=False, base_url=base_url, relative_uris=relative_uris, ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["items", "type", "label", "outputBinding"]) class CommandInputParameter(InputParameter): """ An input parameter for a CommandLineTool. """ id: str def __init__( self, id: Any, label: Optional[Any] = None, secondaryFiles: Optional[Any] = None, streamable: Optional[Any] = None, doc: Optional[Any] = None, format: Optional[Any] = None, inputBinding: Optional[Any] = None, default: Optional[Any] = None, type_: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.label = label self.secondaryFiles = secondaryFiles self.streamable = streamable self.doc = doc self.id = id if id is not None else "_:" + str(_uuid__.uuid4()) self.format = format self.inputBinding = inputBinding self.default = default self.type_ = type_ def __eq__(self, other: Any) -> bool: if isinstance(other, CommandInputParameter): return bool( self.label == other.label and self.secondaryFiles == other.secondaryFiles and self.streamable == other.streamable and self.doc == other.doc and self.id == other.id and self.format == other.format and self.inputBinding == other.inputBinding and self.default == other.default and self.type_ == other.type_ ) return False def __hash__(self) -> int: return hash( ( self.label, self.secondaryFiles, self.streamable, self.doc, self.id, self.format, self.inputBinding, self.default, self.type_, ) ) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "CommandInputParameter": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] id = None if "id" in _doc: try: id = load_field( _doc.get("id"), uri_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("id") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `id`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("id") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `id` field is not valid because:", SourceLine(_doc, "id", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `id` field is not valid because:", SourceLine(_doc, "id", str), [e], detailed_message=f"the `id` field with value `{val}` " "is not valid because:", ) ) __original_id_is_none = id is None if id is None: if docRoot is not None: id = docRoot else: _errors__.append(ValidationException("missing id")) if not __original_id_is_none: baseuri = cast(str, id) label = None if "label" in _doc: try: label = load_field( _doc.get("label"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("label") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `label`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("label") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [e], detailed_message=f"the `label` field with value `{val}` " "is not valid because:", ) ) secondaryFiles = None if "secondaryFiles" in _doc: try: secondaryFiles = load_field( _doc.get("secondaryFiles"), union_of_None_type_or_strtype_or_ExpressionLoader_or_array_of_union_of_strtype_or_ExpressionLoader, baseuri, loadingOptions, lc=_doc.get("secondaryFiles") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `secondaryFiles`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("secondaryFiles") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `secondaryFiles` field is not valid because:", SourceLine(_doc, "secondaryFiles", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `secondaryFiles` field is not valid because:", SourceLine(_doc, "secondaryFiles", str), [e], detailed_message=f"the `secondaryFiles` field with value `{val}` " "is not valid because:", ) ) streamable = None if "streamable" in _doc: try: streamable = load_field( _doc.get("streamable"), union_of_None_type_or_booltype, baseuri, loadingOptions, lc=_doc.get("streamable") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `streamable`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("streamable") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `streamable` field is not valid because:", SourceLine(_doc, "streamable", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `streamable` field is not valid because:", SourceLine(_doc, "streamable", str), [e], detailed_message=f"the `streamable` field with value `{val}` " "is not valid because:", ) ) doc = None if "doc" in _doc: try: doc = load_field( _doc.get("doc"), union_of_None_type_or_strtype_or_array_of_strtype, baseuri, loadingOptions, lc=_doc.get("doc") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `doc`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("doc") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [e], detailed_message=f"the `doc` field with value `{val}` " "is not valid because:", ) ) format = None if "format" in _doc: try: format = load_field( _doc.get("format"), uri_union_of_None_type_or_strtype_or_array_of_strtype_or_ExpressionLoader_True_False_None_True, baseuri, loadingOptions, lc=_doc.get("format") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `format`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("format") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `format` field is not valid because:", SourceLine(_doc, "format", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `format` field is not valid because:", SourceLine(_doc, "format", str), [e], detailed_message=f"the `format` field with value `{val}` " "is not valid because:", ) ) inputBinding = None if "inputBinding" in _doc: try: inputBinding = load_field( _doc.get("inputBinding"), union_of_None_type_or_CommandLineBindingLoader, baseuri, loadingOptions, lc=_doc.get("inputBinding") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `inputBinding`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("inputBinding") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `inputBinding` field is not valid because:", SourceLine(_doc, "inputBinding", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `inputBinding` field is not valid because:", SourceLine(_doc, "inputBinding", str), [e], detailed_message=f"the `inputBinding` field with value `{val}` " "is not valid because:", ) ) default = None if "default" in _doc: try: default = load_field( _doc.get("default"), union_of_None_type_or_CWLObjectTypeLoader, baseuri, loadingOptions, lc=_doc.get("default") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `default`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("default") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `default` field is not valid because:", SourceLine(_doc, "default", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `default` field is not valid because:", SourceLine(_doc, "default", str), [e], detailed_message=f"the `default` field with value `{val}` " "is not valid because:", ) ) type_ = None if "type" in _doc: try: type_ = load_field( _doc.get("type"), typedsl_union_of_None_type_or_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype_2, baseuri, loadingOptions, lc=_doc.get("type") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `type`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("type") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [e], detailed_message=f"the `type` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `label`, `secondaryFiles`, `streamable`, `doc`, `id`, `format`, `inputBinding`, `default`, `type`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( label=label, secondaryFiles=secondaryFiles, streamable=streamable, doc=doc, id=id, format=format, inputBinding=inputBinding, default=default, type_=type_, extension_fields=extension_fields, loadingOptions=loadingOptions, ) loadingOptions.idx[cast(str, id)] = (_constructed, loadingOptions) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.id is not None: u = save_relative_uri(self.id, base_url, True, None, relative_uris) r["id"] = u if self.label is not None: r["label"] = save( self.label, top=False, base_url=self.id, relative_uris=relative_uris ) if self.secondaryFiles is not None: r["secondaryFiles"] = save( self.secondaryFiles, top=False, base_url=self.id, relative_uris=relative_uris, ) if self.streamable is not None: r["streamable"] = save( self.streamable, top=False, base_url=self.id, relative_uris=relative_uris, ) if self.doc is not None: r["doc"] = save( self.doc, top=False, base_url=self.id, relative_uris=relative_uris ) if self.format is not None: u = save_relative_uri(self.format, self.id, True, None, relative_uris) r["format"] = u if self.inputBinding is not None: r["inputBinding"] = save( self.inputBinding, top=False, base_url=self.id, relative_uris=relative_uris, ) if self.default is not None: r["default"] = save( self.default, top=False, base_url=self.id, relative_uris=relative_uris ) if self.type_ is not None: r["type"] = save( self.type_, top=False, base_url=self.id, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset( [ "label", "secondaryFiles", "streamable", "doc", "id", "format", "inputBinding", "default", "type", ] ) class CommandOutputParameter(OutputParameter): """ An output parameter for a CommandLineTool. """ id: str def __init__( self, id: Any, label: Optional[Any] = None, secondaryFiles: Optional[Any] = None, streamable: Optional[Any] = None, doc: Optional[Any] = None, outputBinding: Optional[Any] = None, format: Optional[Any] = None, type_: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.label = label self.secondaryFiles = secondaryFiles self.streamable = streamable self.doc = doc self.id = id if id is not None else "_:" + str(_uuid__.uuid4()) self.outputBinding = outputBinding self.format = format self.type_ = type_ def __eq__(self, other: Any) -> bool: if isinstance(other, CommandOutputParameter): return bool( self.label == other.label and self.secondaryFiles == other.secondaryFiles and self.streamable == other.streamable and self.doc == other.doc and self.id == other.id and self.outputBinding == other.outputBinding and self.format == other.format and self.type_ == other.type_ ) return False def __hash__(self) -> int: return hash( ( self.label, self.secondaryFiles, self.streamable, self.doc, self.id, self.outputBinding, self.format, self.type_, ) ) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "CommandOutputParameter": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] id = None if "id" in _doc: try: id = load_field( _doc.get("id"), uri_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("id") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `id`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("id") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `id` field is not valid because:", SourceLine(_doc, "id", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `id` field is not valid because:", SourceLine(_doc, "id", str), [e], detailed_message=f"the `id` field with value `{val}` " "is not valid because:", ) ) __original_id_is_none = id is None if id is None: if docRoot is not None: id = docRoot else: _errors__.append(ValidationException("missing id")) if not __original_id_is_none: baseuri = cast(str, id) label = None if "label" in _doc: try: label = load_field( _doc.get("label"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("label") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `label`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("label") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [e], detailed_message=f"the `label` field with value `{val}` " "is not valid because:", ) ) secondaryFiles = None if "secondaryFiles" in _doc: try: secondaryFiles = load_field( _doc.get("secondaryFiles"), union_of_None_type_or_strtype_or_ExpressionLoader_or_array_of_union_of_strtype_or_ExpressionLoader, baseuri, loadingOptions, lc=_doc.get("secondaryFiles") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `secondaryFiles`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("secondaryFiles") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `secondaryFiles` field is not valid because:", SourceLine(_doc, "secondaryFiles", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `secondaryFiles` field is not valid because:", SourceLine(_doc, "secondaryFiles", str), [e], detailed_message=f"the `secondaryFiles` field with value `{val}` " "is not valid because:", ) ) streamable = None if "streamable" in _doc: try: streamable = load_field( _doc.get("streamable"), union_of_None_type_or_booltype, baseuri, loadingOptions, lc=_doc.get("streamable") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `streamable`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("streamable") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `streamable` field is not valid because:", SourceLine(_doc, "streamable", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `streamable` field is not valid because:", SourceLine(_doc, "streamable", str), [e], detailed_message=f"the `streamable` field with value `{val}` " "is not valid because:", ) ) doc = None if "doc" in _doc: try: doc = load_field( _doc.get("doc"), union_of_None_type_or_strtype_or_array_of_strtype, baseuri, loadingOptions, lc=_doc.get("doc") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `doc`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("doc") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [e], detailed_message=f"the `doc` field with value `{val}` " "is not valid because:", ) ) outputBinding = None if "outputBinding" in _doc: try: outputBinding = load_field( _doc.get("outputBinding"), union_of_None_type_or_CommandOutputBindingLoader, baseuri, loadingOptions, lc=_doc.get("outputBinding") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `outputBinding`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("outputBinding") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `outputBinding` field is not valid because:", SourceLine(_doc, "outputBinding", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `outputBinding` field is not valid because:", SourceLine(_doc, "outputBinding", str), [e], detailed_message=f"the `outputBinding` field with value `{val}` " "is not valid because:", ) ) format = None if "format" in _doc: try: format = load_field( _doc.get("format"), uri_union_of_None_type_or_strtype_or_ExpressionLoader_True_False_None_True, baseuri, loadingOptions, lc=_doc.get("format") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `format`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("format") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `format` field is not valid because:", SourceLine(_doc, "format", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `format` field is not valid because:", SourceLine(_doc, "format", str), [e], detailed_message=f"the `format` field with value `{val}` " "is not valid because:", ) ) type_ = None if "type" in _doc: try: type_ = load_field( _doc.get("type"), typedsl_union_of_None_type_or_CWLTypeLoader_or_stdoutLoader_or_stderrLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype_2, baseuri, loadingOptions, lc=_doc.get("type") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `type`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("type") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [e], detailed_message=f"the `type` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `label`, `secondaryFiles`, `streamable`, `doc`, `id`, `outputBinding`, `format`, `type`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( label=label, secondaryFiles=secondaryFiles, streamable=streamable, doc=doc, id=id, outputBinding=outputBinding, format=format, type_=type_, extension_fields=extension_fields, loadingOptions=loadingOptions, ) loadingOptions.idx[cast(str, id)] = (_constructed, loadingOptions) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.id is not None: u = save_relative_uri(self.id, base_url, True, None, relative_uris) r["id"] = u if self.label is not None: r["label"] = save( self.label, top=False, base_url=self.id, relative_uris=relative_uris ) if self.secondaryFiles is not None: r["secondaryFiles"] = save( self.secondaryFiles, top=False, base_url=self.id, relative_uris=relative_uris, ) if self.streamable is not None: r["streamable"] = save( self.streamable, top=False, base_url=self.id, relative_uris=relative_uris, ) if self.doc is not None: r["doc"] = save( self.doc, top=False, base_url=self.id, relative_uris=relative_uris ) if self.outputBinding is not None: r["outputBinding"] = save( self.outputBinding, top=False, base_url=self.id, relative_uris=relative_uris, ) if self.format is not None: u = save_relative_uri(self.format, self.id, True, None, relative_uris) r["format"] = u if self.type_ is not None: r["type"] = save( self.type_, top=False, base_url=self.id, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset( [ "label", "secondaryFiles", "streamable", "doc", "id", "outputBinding", "format", "type", ] ) class CommandLineTool(Process): """ This defines the schema of the CWL Command Line Tool Description document. """ id: str def __init__( self, inputs: Any, outputs: Any, id: Optional[Any] = None, requirements: Optional[Any] = None, hints: Optional[Any] = None, label: Optional[Any] = None, doc: Optional[Any] = None, cwlVersion: Optional[Any] = None, baseCommand: Optional[Any] = None, arguments: Optional[Any] = None, stdin: Optional[Any] = None, stderr: Optional[Any] = None, stdout: Optional[Any] = None, successCodes: Optional[Any] = None, temporaryFailCodes: Optional[Any] = None, permanentFailCodes: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.id = id if id is not None else "_:" + str(_uuid__.uuid4()) self.inputs = inputs self.outputs = outputs self.requirements = requirements self.hints = hints self.label = label self.doc = doc self.cwlVersion = cwlVersion self.class_ = "CommandLineTool" self.baseCommand = baseCommand self.arguments = arguments self.stdin = stdin self.stderr = stderr self.stdout = stdout self.successCodes = successCodes self.temporaryFailCodes = temporaryFailCodes self.permanentFailCodes = permanentFailCodes def __eq__(self, other: Any) -> bool: if isinstance(other, CommandLineTool): return bool( self.id == other.id and self.inputs == other.inputs and self.outputs == other.outputs and self.requirements == other.requirements and self.hints == other.hints and self.label == other.label and self.doc == other.doc and self.cwlVersion == other.cwlVersion and self.class_ == other.class_ and self.baseCommand == other.baseCommand and self.arguments == other.arguments and self.stdin == other.stdin and self.stderr == other.stderr and self.stdout == other.stdout and self.successCodes == other.successCodes and self.temporaryFailCodes == other.temporaryFailCodes and self.permanentFailCodes == other.permanentFailCodes ) return False def __hash__(self) -> int: return hash( ( self.id, self.inputs, self.outputs, self.requirements, self.hints, self.label, self.doc, self.cwlVersion, self.class_, self.baseCommand, self.arguments, self.stdin, self.stderr, self.stdout, self.successCodes, self.temporaryFailCodes, self.permanentFailCodes, ) ) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "CommandLineTool": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] id = None if "id" in _doc: try: id = load_field( _doc.get("id"), uri_union_of_None_type_or_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("id") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `id`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("id") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `id` field is not valid because:", SourceLine(_doc, "id", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `id` field is not valid because:", SourceLine(_doc, "id", str), [e], detailed_message=f"the `id` field with value `{val}` " "is not valid because:", ) ) __original_id_is_none = id is None if id is None: if docRoot is not None: id = docRoot else: id = "_:" + str(_uuid__.uuid4()) if not __original_id_is_none: baseuri = cast(str, id) try: if _doc.get("class") is None: raise ValidationException("missing required field `class`", None, []) class_ = load_field( _doc.get("class"), uri_CommandLineTool_classLoader_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("class") ) if class_ not in (cls.__name__, loadingOptions.vocab.get(cls.__name__)): raise ValidationException(f"tried `{cls.__name__}` but") except ValidationException as e: raise e try: if _doc.get("inputs") is None: raise ValidationException("missing required field `inputs`", None, []) inputs = load_field( _doc.get("inputs"), idmap_inputs_array_of_CommandInputParameterLoader, baseuri, loadingOptions, lc=_doc.get("inputs") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `inputs`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("inputs") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `inputs` field is not valid because:", SourceLine(_doc, "inputs", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `inputs` field is not valid because:", SourceLine(_doc, "inputs", str), [e], detailed_message=f"the `inputs` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("outputs") is None: raise ValidationException("missing required field `outputs`", None, []) outputs = load_field( _doc.get("outputs"), idmap_outputs_array_of_CommandOutputParameterLoader, baseuri, loadingOptions, lc=_doc.get("outputs") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `outputs`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("outputs") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `outputs` field is not valid because:", SourceLine(_doc, "outputs", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `outputs` field is not valid because:", SourceLine(_doc, "outputs", str), [e], detailed_message=f"the `outputs` field with value `{val}` " "is not valid because:", ) ) requirements = None if "requirements" in _doc: try: requirements = load_field( _doc.get("requirements"), idmap_requirements_union_of_None_type_or_array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader_or_LoadListingRequirementLoader_or_InplaceUpdateRequirementLoader_or_SecretsLoader_or_TimeLimitLoader_or_WorkReuseLoader_or_NetworkAccessLoader_or_MPIRequirementLoader_or_CUDARequirementLoader_or_ShmSizeLoader, baseuri, loadingOptions, lc=_doc.get("requirements") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `requirements`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("requirements") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `requirements` field is not valid because:", SourceLine(_doc, "requirements", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `requirements` field is not valid because:", SourceLine(_doc, "requirements", str), [e], detailed_message=f"the `requirements` field with value `{val}` " "is not valid because:", ) ) hints = None if "hints" in _doc: try: hints = load_field( _doc.get("hints"), idmap_hints_union_of_None_type_or_array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader_or_LoadListingRequirementLoader_or_InplaceUpdateRequirementLoader_or_SecretsLoader_or_TimeLimitLoader_or_WorkReuseLoader_or_NetworkAccessLoader_or_MPIRequirementLoader_or_CUDARequirementLoader_or_ShmSizeLoader_or_Any_type, baseuri, loadingOptions, lc=_doc.get("hints") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `hints`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("hints") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `hints` field is not valid because:", SourceLine(_doc, "hints", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `hints` field is not valid because:", SourceLine(_doc, "hints", str), [e], detailed_message=f"the `hints` field with value `{val}` " "is not valid because:", ) ) label = None if "label" in _doc: try: label = load_field( _doc.get("label"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("label") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `label`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("label") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [e], detailed_message=f"the `label` field with value `{val}` " "is not valid because:", ) ) doc = None if "doc" in _doc: try: doc = load_field( _doc.get("doc"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("doc") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `doc`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("doc") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [e], detailed_message=f"the `doc` field with value `{val}` " "is not valid because:", ) ) cwlVersion = None if "cwlVersion" in _doc: try: cwlVersion = load_field( _doc.get("cwlVersion"), uri_union_of_None_type_or_CWLVersionLoader_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("cwlVersion") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `cwlVersion`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("cwlVersion") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `cwlVersion` field is not valid because:", SourceLine(_doc, "cwlVersion", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `cwlVersion` field is not valid because:", SourceLine(_doc, "cwlVersion", str), [e], detailed_message=f"the `cwlVersion` field with value `{val}` " "is not valid because:", ) ) baseCommand = None if "baseCommand" in _doc: try: baseCommand = load_field( _doc.get("baseCommand"), union_of_None_type_or_strtype_or_array_of_strtype, baseuri, loadingOptions, lc=_doc.get("baseCommand") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `baseCommand`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("baseCommand") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `baseCommand` field is not valid because:", SourceLine(_doc, "baseCommand", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `baseCommand` field is not valid because:", SourceLine(_doc, "baseCommand", str), [e], detailed_message=f"the `baseCommand` field with value `{val}` " "is not valid because:", ) ) arguments = None if "arguments" in _doc: try: arguments = load_field( _doc.get("arguments"), union_of_None_type_or_array_of_union_of_strtype_or_ExpressionLoader_or_CommandLineBindingLoader, baseuri, loadingOptions, lc=_doc.get("arguments") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `arguments`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("arguments") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `arguments` field is not valid because:", SourceLine(_doc, "arguments", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `arguments` field is not valid because:", SourceLine(_doc, "arguments", str), [e], detailed_message=f"the `arguments` field with value `{val}` " "is not valid because:", ) ) stdin = None if "stdin" in _doc: try: stdin = load_field( _doc.get("stdin"), union_of_None_type_or_strtype_or_ExpressionLoader, baseuri, loadingOptions, lc=_doc.get("stdin") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `stdin`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("stdin") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `stdin` field is not valid because:", SourceLine(_doc, "stdin", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `stdin` field is not valid because:", SourceLine(_doc, "stdin", str), [e], detailed_message=f"the `stdin` field with value `{val}` " "is not valid because:", ) ) stderr = None if "stderr" in _doc: try: stderr = load_field( _doc.get("stderr"), union_of_None_type_or_strtype_or_ExpressionLoader, baseuri, loadingOptions, lc=_doc.get("stderr") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `stderr`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("stderr") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `stderr` field is not valid because:", SourceLine(_doc, "stderr", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `stderr` field is not valid because:", SourceLine(_doc, "stderr", str), [e], detailed_message=f"the `stderr` field with value `{val}` " "is not valid because:", ) ) stdout = None if "stdout" in _doc: try: stdout = load_field( _doc.get("stdout"), union_of_None_type_or_strtype_or_ExpressionLoader, baseuri, loadingOptions, lc=_doc.get("stdout") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `stdout`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("stdout") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `stdout` field is not valid because:", SourceLine(_doc, "stdout", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `stdout` field is not valid because:", SourceLine(_doc, "stdout", str), [e], detailed_message=f"the `stdout` field with value `{val}` " "is not valid because:", ) ) successCodes = None if "successCodes" in _doc: try: successCodes = load_field( _doc.get("successCodes"), union_of_None_type_or_array_of_inttype, baseuri, loadingOptions, lc=_doc.get("successCodes") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `successCodes`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("successCodes") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `successCodes` field is not valid because:", SourceLine(_doc, "successCodes", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `successCodes` field is not valid because:", SourceLine(_doc, "successCodes", str), [e], detailed_message=f"the `successCodes` field with value `{val}` " "is not valid because:", ) ) temporaryFailCodes = None if "temporaryFailCodes" in _doc: try: temporaryFailCodes = load_field( _doc.get("temporaryFailCodes"), union_of_None_type_or_array_of_inttype, baseuri, loadingOptions, lc=_doc.get("temporaryFailCodes") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `temporaryFailCodes`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("temporaryFailCodes") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `temporaryFailCodes` field is not valid because:", SourceLine(_doc, "temporaryFailCodes", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `temporaryFailCodes` field is not valid because:", SourceLine(_doc, "temporaryFailCodes", str), [e], detailed_message=f"the `temporaryFailCodes` field with value `{val}` " "is not valid because:", ) ) permanentFailCodes = None if "permanentFailCodes" in _doc: try: permanentFailCodes = load_field( _doc.get("permanentFailCodes"), union_of_None_type_or_array_of_inttype, baseuri, loadingOptions, lc=_doc.get("permanentFailCodes") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `permanentFailCodes`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("permanentFailCodes") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `permanentFailCodes` field is not valid because:", SourceLine(_doc, "permanentFailCodes", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `permanentFailCodes` field is not valid because:", SourceLine(_doc, "permanentFailCodes", str), [e], detailed_message=f"the `permanentFailCodes` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `id`, `inputs`, `outputs`, `requirements`, `hints`, `label`, `doc`, `cwlVersion`, `class`, `baseCommand`, `arguments`, `stdin`, `stderr`, `stdout`, `successCodes`, `temporaryFailCodes`, `permanentFailCodes`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( id=id, inputs=inputs, outputs=outputs, requirements=requirements, hints=hints, label=label, doc=doc, cwlVersion=cwlVersion, baseCommand=baseCommand, arguments=arguments, stdin=stdin, stderr=stderr, stdout=stdout, successCodes=successCodes, temporaryFailCodes=temporaryFailCodes, permanentFailCodes=permanentFailCodes, extension_fields=extension_fields, loadingOptions=loadingOptions, ) loadingOptions.idx[cast(str, id)] = (_constructed, loadingOptions) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.id is not None: u = save_relative_uri(self.id, base_url, True, None, relative_uris) r["id"] = u if self.class_ is not None: uri = self.loadingOptions.vocab[self.class_] if p := self.loadingOptions.rvocab.get(uri[: -len(self.class_)]): uri = f"{p}:{self.class_}" else: uri = self.class_ u = save_relative_uri(uri, self.id, False, None, relative_uris) r["class"] = u if self.inputs is not None: r["inputs"] = save( self.inputs, top=False, base_url=self.id, relative_uris=relative_uris ) if self.outputs is not None: r["outputs"] = save( self.outputs, top=False, base_url=self.id, relative_uris=relative_uris ) if self.requirements is not None: r["requirements"] = save( self.requirements, top=False, base_url=self.id, relative_uris=relative_uris, ) if self.hints is not None: r["hints"] = save( self.hints, top=False, base_url=self.id, relative_uris=relative_uris ) if self.label is not None: r["label"] = save( self.label, top=False, base_url=self.id, relative_uris=relative_uris ) if self.doc is not None: r["doc"] = save( self.doc, top=False, base_url=self.id, relative_uris=relative_uris ) if self.cwlVersion is not None: u = save_relative_uri(self.cwlVersion, self.id, False, None, relative_uris) r["cwlVersion"] = u if self.baseCommand is not None: r["baseCommand"] = save( self.baseCommand, top=False, base_url=self.id, relative_uris=relative_uris, ) if self.arguments is not None: r["arguments"] = save( self.arguments, top=False, base_url=self.id, relative_uris=relative_uris ) if self.stdin is not None: r["stdin"] = save( self.stdin, top=False, base_url=self.id, relative_uris=relative_uris ) if self.stderr is not None: r["stderr"] = save( self.stderr, top=False, base_url=self.id, relative_uris=relative_uris ) if self.stdout is not None: r["stdout"] = save( self.stdout, top=False, base_url=self.id, relative_uris=relative_uris ) if self.successCodes is not None: r["successCodes"] = save( self.successCodes, top=False, base_url=self.id, relative_uris=relative_uris, ) if self.temporaryFailCodes is not None: r["temporaryFailCodes"] = save( self.temporaryFailCodes, top=False, base_url=self.id, relative_uris=relative_uris, ) if self.permanentFailCodes is not None: r["permanentFailCodes"] = save( self.permanentFailCodes, top=False, base_url=self.id, relative_uris=relative_uris, ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset( [ "id", "inputs", "outputs", "requirements", "hints", "label", "doc", "cwlVersion", "class", "baseCommand", "arguments", "stdin", "stderr", "stdout", "successCodes", "temporaryFailCodes", "permanentFailCodes", ] ) class DockerRequirement(ProcessRequirement): """ Indicates that a workflow component should be run in a [Docker](http://docker.com) container, and specifies how to fetch or build the image. If a CommandLineTool lists `DockerRequirement` under `hints` (or `requirements`), it may (or must) be run in the specified Docker container. The platform must first acquire or install the correct Docker image as specified by `dockerPull`, `dockerImport`, `dockerLoad` or `dockerFile`. The platform must execute the tool in the container using `docker run` with the appropriate Docker image and tool command line. The workflow platform may provide input files and the designated output directory through the use of volume bind mounts. The platform should rewrite file paths in the input object to correspond to the Docker bind mounted locations. That is, the platform should rewrite values in the parameter context such as `runtime.outdir`, `runtime.tmpdir` and others to be valid paths within the container. When running a tool contained in Docker, the workflow platform must not assume anything about the contents of the Docker container, such as the presence or absence of specific software, except to assume that the generated command line represents a valid command within the runtime environment of the container. ## Interaction with other requirements If [EnvVarRequirement](#EnvVarRequirement) is specified alongside a DockerRequirement, the environment variables must be provided to Docker using `--env` or `--env-file` and interact with the container's preexisting environment as defined by Docker. """ def __init__( self, dockerPull: Optional[Any] = None, dockerLoad: Optional[Any] = None, dockerFile: Optional[Any] = None, dockerImport: Optional[Any] = None, dockerImageId: Optional[Any] = None, dockerOutputDirectory: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.class_ = "DockerRequirement" self.dockerPull = dockerPull self.dockerLoad = dockerLoad self.dockerFile = dockerFile self.dockerImport = dockerImport self.dockerImageId = dockerImageId self.dockerOutputDirectory = dockerOutputDirectory def __eq__(self, other: Any) -> bool: if isinstance(other, DockerRequirement): return bool( self.class_ == other.class_ and self.dockerPull == other.dockerPull and self.dockerLoad == other.dockerLoad and self.dockerFile == other.dockerFile and self.dockerImport == other.dockerImport and self.dockerImageId == other.dockerImageId and self.dockerOutputDirectory == other.dockerOutputDirectory ) return False def __hash__(self) -> int: return hash( ( self.class_, self.dockerPull, self.dockerLoad, self.dockerFile, self.dockerImport, self.dockerImageId, self.dockerOutputDirectory, ) ) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "DockerRequirement": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("class") is None: raise ValidationException("missing required field `class`", None, []) class_ = load_field( _doc.get("class"), uri_DockerRequirement_classLoader_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("class") ) if class_ not in (cls.__name__, loadingOptions.vocab.get(cls.__name__)): raise ValidationException(f"tried `{cls.__name__}` but") except ValidationException as e: raise e dockerPull = None if "dockerPull" in _doc: try: dockerPull = load_field( _doc.get("dockerPull"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("dockerPull") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `dockerPull`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("dockerPull") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `dockerPull` field is not valid because:", SourceLine(_doc, "dockerPull", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `dockerPull` field is not valid because:", SourceLine(_doc, "dockerPull", str), [e], detailed_message=f"the `dockerPull` field with value `{val}` " "is not valid because:", ) ) dockerLoad = None if "dockerLoad" in _doc: try: dockerLoad = load_field( _doc.get("dockerLoad"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("dockerLoad") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `dockerLoad`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("dockerLoad") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `dockerLoad` field is not valid because:", SourceLine(_doc, "dockerLoad", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `dockerLoad` field is not valid because:", SourceLine(_doc, "dockerLoad", str), [e], detailed_message=f"the `dockerLoad` field with value `{val}` " "is not valid because:", ) ) dockerFile = None if "dockerFile" in _doc: try: dockerFile = load_field( _doc.get("dockerFile"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("dockerFile") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `dockerFile`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("dockerFile") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `dockerFile` field is not valid because:", SourceLine(_doc, "dockerFile", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `dockerFile` field is not valid because:", SourceLine(_doc, "dockerFile", str), [e], detailed_message=f"the `dockerFile` field with value `{val}` " "is not valid because:", ) ) dockerImport = None if "dockerImport" in _doc: try: dockerImport = load_field( _doc.get("dockerImport"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("dockerImport") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `dockerImport`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("dockerImport") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `dockerImport` field is not valid because:", SourceLine(_doc, "dockerImport", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `dockerImport` field is not valid because:", SourceLine(_doc, "dockerImport", str), [e], detailed_message=f"the `dockerImport` field with value `{val}` " "is not valid because:", ) ) dockerImageId = None if "dockerImageId" in _doc: try: dockerImageId = load_field( _doc.get("dockerImageId"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("dockerImageId") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `dockerImageId`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("dockerImageId") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `dockerImageId` field is not valid because:", SourceLine(_doc, "dockerImageId", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `dockerImageId` field is not valid because:", SourceLine(_doc, "dockerImageId", str), [e], detailed_message=f"the `dockerImageId` field with value `{val}` " "is not valid because:", ) ) dockerOutputDirectory = None if "dockerOutputDirectory" in _doc: try: dockerOutputDirectory = load_field( _doc.get("dockerOutputDirectory"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("dockerOutputDirectory") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `dockerOutputDirectory`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("dockerOutputDirectory") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `dockerOutputDirectory` field is not valid because:", SourceLine(_doc, "dockerOutputDirectory", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `dockerOutputDirectory` field is not valid because:", SourceLine(_doc, "dockerOutputDirectory", str), [e], detailed_message=f"the `dockerOutputDirectory` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `class`, `dockerPull`, `dockerLoad`, `dockerFile`, `dockerImport`, `dockerImageId`, `dockerOutputDirectory`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( dockerPull=dockerPull, dockerLoad=dockerLoad, dockerFile=dockerFile, dockerImport=dockerImport, dockerImageId=dockerImageId, dockerOutputDirectory=dockerOutputDirectory, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.class_ is not None: uri = self.loadingOptions.vocab[self.class_] if p := self.loadingOptions.rvocab.get(uri[: -len(self.class_)]): uri = f"{p}:{self.class_}" else: uri = self.class_ u = save_relative_uri(uri, base_url, False, None, relative_uris) r["class"] = u if self.dockerPull is not None: r["dockerPull"] = save( self.dockerPull, top=False, base_url=base_url, relative_uris=relative_uris, ) if self.dockerLoad is not None: r["dockerLoad"] = save( self.dockerLoad, top=False, base_url=base_url, relative_uris=relative_uris, ) if self.dockerFile is not None: r["dockerFile"] = save( self.dockerFile, top=False, base_url=base_url, relative_uris=relative_uris, ) if self.dockerImport is not None: r["dockerImport"] = save( self.dockerImport, top=False, base_url=base_url, relative_uris=relative_uris, ) if self.dockerImageId is not None: r["dockerImageId"] = save( self.dockerImageId, top=False, base_url=base_url, relative_uris=relative_uris, ) if self.dockerOutputDirectory is not None: r["dockerOutputDirectory"] = save( self.dockerOutputDirectory, top=False, base_url=base_url, relative_uris=relative_uris, ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset( [ "class", "dockerPull", "dockerLoad", "dockerFile", "dockerImport", "dockerImageId", "dockerOutputDirectory", ] ) class SoftwareRequirement(ProcessRequirement): """ A list of software packages that should be configured in the environment of the defined process. """ def __init__( self, packages: Any, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.class_ = "SoftwareRequirement" self.packages = packages def __eq__(self, other: Any) -> bool: if isinstance(other, SoftwareRequirement): return bool(self.class_ == other.class_ and self.packages == other.packages) return False def __hash__(self) -> int: return hash((self.class_, self.packages)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "SoftwareRequirement": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("class") is None: raise ValidationException("missing required field `class`", None, []) class_ = load_field( _doc.get("class"), uri_SoftwareRequirement_classLoader_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("class") ) if class_ not in (cls.__name__, loadingOptions.vocab.get(cls.__name__)): raise ValidationException(f"tried `{cls.__name__}` but") except ValidationException as e: raise e try: if _doc.get("packages") is None: raise ValidationException("missing required field `packages`", None, []) packages = load_field( _doc.get("packages"), idmap_packages_array_of_SoftwarePackageLoader, baseuri, loadingOptions, lc=_doc.get("packages") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `packages`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("packages") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `packages` field is not valid because:", SourceLine(_doc, "packages", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `packages` field is not valid because:", SourceLine(_doc, "packages", str), [e], detailed_message=f"the `packages` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `class`, `packages`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( packages=packages, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.class_ is not None: uri = self.loadingOptions.vocab[self.class_] if p := self.loadingOptions.rvocab.get(uri[: -len(self.class_)]): uri = f"{p}:{self.class_}" else: uri = self.class_ u = save_relative_uri(uri, base_url, False, None, relative_uris) r["class"] = u if self.packages is not None: r["packages"] = save( self.packages, top=False, base_url=base_url, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["class", "packages"]) class SoftwarePackage(Saveable): def __init__( self, package: Any, version: Optional[Any] = None, specs: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.package = package self.version = version self.specs = specs def __eq__(self, other: Any) -> bool: if isinstance(other, SoftwarePackage): return bool( self.package == other.package and self.version == other.version and self.specs == other.specs ) return False def __hash__(self) -> int: return hash((self.package, self.version, self.specs)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "SoftwarePackage": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("package") is None: raise ValidationException("missing required field `package`", None, []) package = load_field( _doc.get("package"), strtype, baseuri, loadingOptions, lc=_doc.get("package") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `package`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("package") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `package` field is not valid because:", SourceLine(_doc, "package", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `package` field is not valid because:", SourceLine(_doc, "package", str), [e], detailed_message=f"the `package` field with value `{val}` " "is not valid because:", ) ) version = None if "version" in _doc: try: version = load_field( _doc.get("version"), union_of_None_type_or_array_of_strtype, baseuri, loadingOptions, lc=_doc.get("version") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `version`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("version") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `version` field is not valid because:", SourceLine(_doc, "version", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `version` field is not valid because:", SourceLine(_doc, "version", str), [e], detailed_message=f"the `version` field with value `{val}` " "is not valid because:", ) ) specs = None if "specs" in _doc: try: specs = load_field( _doc.get("specs"), uri_union_of_None_type_or_array_of_strtype_False_False_None_True, baseuri, loadingOptions, lc=_doc.get("specs") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `specs`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("specs") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `specs` field is not valid because:", SourceLine(_doc, "specs", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `specs` field is not valid because:", SourceLine(_doc, "specs", str), [e], detailed_message=f"the `specs` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `package`, `version`, `specs`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( package=package, version=version, specs=specs, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.package is not None: r["package"] = save( self.package, top=False, base_url=base_url, relative_uris=relative_uris ) if self.version is not None: r["version"] = save( self.version, top=False, base_url=base_url, relative_uris=relative_uris ) if self.specs is not None: u = save_relative_uri(self.specs, base_url, False, None, relative_uris) r["specs"] = u # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["package", "version", "specs"]) class Dirent(Saveable): """ Define a file or subdirectory that must be placed in the designated output directory prior to executing the command line tool. May be the result of executing an expression, such as building a configuration file from a template. """ def __init__( self, entry: Any, entryname: Optional[Any] = None, writable: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.entryname = entryname self.entry = entry self.writable = writable def __eq__(self, other: Any) -> bool: if isinstance(other, Dirent): return bool( self.entryname == other.entryname and self.entry == other.entry and self.writable == other.writable ) return False def __hash__(self) -> int: return hash((self.entryname, self.entry, self.writable)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "Dirent": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] entryname = None if "entryname" in _doc: try: entryname = load_field( _doc.get("entryname"), union_of_None_type_or_strtype_or_ExpressionLoader, baseuri, loadingOptions, lc=_doc.get("entryname") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `entryname`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("entryname") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `entryname` field is not valid because:", SourceLine(_doc, "entryname", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `entryname` field is not valid because:", SourceLine(_doc, "entryname", str), [e], detailed_message=f"the `entryname` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("entry") is None: raise ValidationException("missing required field `entry`", None, []) entry = load_field( _doc.get("entry"), union_of_strtype_or_ExpressionLoader, baseuri, loadingOptions, lc=_doc.get("entry") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `entry`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("entry") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `entry` field is not valid because:", SourceLine(_doc, "entry", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `entry` field is not valid because:", SourceLine(_doc, "entry", str), [e], detailed_message=f"the `entry` field with value `{val}` " "is not valid because:", ) ) writable = None if "writable" in _doc: try: writable = load_field( _doc.get("writable"), union_of_None_type_or_booltype, baseuri, loadingOptions, lc=_doc.get("writable") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `writable`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("writable") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `writable` field is not valid because:", SourceLine(_doc, "writable", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `writable` field is not valid because:", SourceLine(_doc, "writable", str), [e], detailed_message=f"the `writable` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `entryname`, `entry`, `writable`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( entryname=entryname, entry=entry, writable=writable, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.entryname is not None: r["entryname"] = save( self.entryname, top=False, base_url=base_url, relative_uris=relative_uris, ) if self.entry is not None: r["entry"] = save( self.entry, top=False, base_url=base_url, relative_uris=relative_uris ) if self.writable is not None: r["writable"] = save( self.writable, top=False, base_url=base_url, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["entryname", "entry", "writable"]) class InitialWorkDirRequirement(ProcessRequirement): """ Define a list of files and subdirectories that must be created by the workflow platform in the designated output directory prior to executing the command line tool. """ def __init__( self, listing: Any, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.class_ = "InitialWorkDirRequirement" self.listing = listing def __eq__(self, other: Any) -> bool: if isinstance(other, InitialWorkDirRequirement): return bool(self.class_ == other.class_ and self.listing == other.listing) return False def __hash__(self) -> int: return hash((self.class_, self.listing)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "InitialWorkDirRequirement": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("class") is None: raise ValidationException("missing required field `class`", None, []) class_ = load_field( _doc.get("class"), uri_InitialWorkDirRequirement_classLoader_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("class") ) if class_ not in (cls.__name__, loadingOptions.vocab.get(cls.__name__)): raise ValidationException(f"tried `{cls.__name__}` but") except ValidationException as e: raise e try: if _doc.get("listing") is None: raise ValidationException("missing required field `listing`", None, []) listing = load_field( _doc.get("listing"), union_of_array_of_union_of_FileLoader_or_DirectoryLoader_or_DirentLoader_or_strtype_or_ExpressionLoader_or_strtype_or_ExpressionLoader, baseuri, loadingOptions, lc=_doc.get("listing") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `listing`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("listing") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `listing` field is not valid because:", SourceLine(_doc, "listing", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `listing` field is not valid because:", SourceLine(_doc, "listing", str), [e], detailed_message=f"the `listing` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `class`, `listing`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( listing=listing, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.class_ is not None: uri = self.loadingOptions.vocab[self.class_] if p := self.loadingOptions.rvocab.get(uri[: -len(self.class_)]): uri = f"{p}:{self.class_}" else: uri = self.class_ u = save_relative_uri(uri, base_url, False, None, relative_uris) r["class"] = u if self.listing is not None: r["listing"] = save( self.listing, top=False, base_url=base_url, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["class", "listing"]) class EnvVarRequirement(ProcessRequirement): """ Define a list of environment variables which will be set in the execution environment of the tool. See `EnvironmentDef` for details. """ def __init__( self, envDef: Any, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.class_ = "EnvVarRequirement" self.envDef = envDef def __eq__(self, other: Any) -> bool: if isinstance(other, EnvVarRequirement): return bool(self.class_ == other.class_ and self.envDef == other.envDef) return False def __hash__(self) -> int: return hash((self.class_, self.envDef)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "EnvVarRequirement": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("class") is None: raise ValidationException("missing required field `class`", None, []) class_ = load_field( _doc.get("class"), uri_EnvVarRequirement_classLoader_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("class") ) if class_ not in (cls.__name__, loadingOptions.vocab.get(cls.__name__)): raise ValidationException(f"tried `{cls.__name__}` but") except ValidationException as e: raise e try: if _doc.get("envDef") is None: raise ValidationException("missing required field `envDef`", None, []) envDef = load_field( _doc.get("envDef"), idmap_envDef_array_of_EnvironmentDefLoader, baseuri, loadingOptions, lc=_doc.get("envDef") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `envDef`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("envDef") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `envDef` field is not valid because:", SourceLine(_doc, "envDef", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `envDef` field is not valid because:", SourceLine(_doc, "envDef", str), [e], detailed_message=f"the `envDef` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `class`, `envDef`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( envDef=envDef, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.class_ is not None: uri = self.loadingOptions.vocab[self.class_] if p := self.loadingOptions.rvocab.get(uri[: -len(self.class_)]): uri = f"{p}:{self.class_}" else: uri = self.class_ u = save_relative_uri(uri, base_url, False, None, relative_uris) r["class"] = u if self.envDef is not None: r["envDef"] = save( self.envDef, top=False, base_url=base_url, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["class", "envDef"]) class ShellCommandRequirement(ProcessRequirement): """ Modify the behavior of CommandLineTool to generate a single string containing a shell command line. Each item in the argument list must be joined into a string separated by single spaces and quoted to prevent intepretation by the shell, unless `CommandLineBinding` for that argument contains `shellQuote: false`. If `shellQuote: false` is specified, the argument is joined into the command string without quoting, which allows the use of shell metacharacters such as `|` for pipes. """ def __init__( self, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.class_ = "ShellCommandRequirement" def __eq__(self, other: Any) -> bool: if isinstance(other, ShellCommandRequirement): return bool(self.class_ == other.class_) return False def __hash__(self) -> int: return hash((self.class_)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "ShellCommandRequirement": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("class") is None: raise ValidationException("missing required field `class`", None, []) class_ = load_field( _doc.get("class"), uri_ShellCommandRequirement_classLoader_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("class") ) if class_ not in (cls.__name__, loadingOptions.vocab.get(cls.__name__)): raise ValidationException(f"tried `{cls.__name__}` but") except ValidationException as e: raise e extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `class`".format(k), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.class_ is not None: uri = self.loadingOptions.vocab[self.class_] if p := self.loadingOptions.rvocab.get(uri[: -len(self.class_)]): uri = f"{p}:{self.class_}" else: uri = self.class_ u = save_relative_uri(uri, base_url, False, None, relative_uris) r["class"] = u # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["class"]) class ResourceRequirement(ProcessRequirement): """ Specify basic hardware resource requirements. "min" is the minimum amount of a resource that must be reserved to schedule a job. If "min" cannot be satisfied, the job should not be run. "max" is the maximum amount of a resource that the job shall be permitted to use. If a node has sufficient resources, multiple jobs may be scheduled on a single node provided each job's "max" resource requirements are met. If a job attempts to exceed its "max" resource allocation, an implementation may deny additional resources, which may result in job failure. If "min" is specified but "max" is not, then "max" == "min" If "max" is specified by "min" is not, then "min" == "max". It is an error if max < min. It is an error if the value of any of these fields is negative. If neither "min" nor "max" is specified for a resource, an implementation may provide a default. """ def __init__( self, coresMin: Optional[Any] = None, coresMax: Optional[Any] = None, ramMin: Optional[Any] = None, ramMax: Optional[Any] = None, tmpdirMin: Optional[Any] = None, tmpdirMax: Optional[Any] = None, outdirMin: Optional[Any] = None, outdirMax: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.class_ = "ResourceRequirement" self.coresMin = coresMin self.coresMax = coresMax self.ramMin = ramMin self.ramMax = ramMax self.tmpdirMin = tmpdirMin self.tmpdirMax = tmpdirMax self.outdirMin = outdirMin self.outdirMax = outdirMax def __eq__(self, other: Any) -> bool: if isinstance(other, ResourceRequirement): return bool( self.class_ == other.class_ and self.coresMin == other.coresMin and self.coresMax == other.coresMax and self.ramMin == other.ramMin and self.ramMax == other.ramMax and self.tmpdirMin == other.tmpdirMin and self.tmpdirMax == other.tmpdirMax and self.outdirMin == other.outdirMin and self.outdirMax == other.outdirMax ) return False def __hash__(self) -> int: return hash( ( self.class_, self.coresMin, self.coresMax, self.ramMin, self.ramMax, self.tmpdirMin, self.tmpdirMax, self.outdirMin, self.outdirMax, ) ) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "ResourceRequirement": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("class") is None: raise ValidationException("missing required field `class`", None, []) class_ = load_field( _doc.get("class"), uri_ResourceRequirement_classLoader_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("class") ) if class_ not in (cls.__name__, loadingOptions.vocab.get(cls.__name__)): raise ValidationException(f"tried `{cls.__name__}` but") except ValidationException as e: raise e coresMin = None if "coresMin" in _doc: try: coresMin = load_field( _doc.get("coresMin"), union_of_None_type_or_inttype_or_strtype_or_ExpressionLoader, baseuri, loadingOptions, lc=_doc.get("coresMin") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `coresMin`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("coresMin") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `coresMin` field is not valid because:", SourceLine(_doc, "coresMin", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `coresMin` field is not valid because:", SourceLine(_doc, "coresMin", str), [e], detailed_message=f"the `coresMin` field with value `{val}` " "is not valid because:", ) ) coresMax = None if "coresMax" in _doc: try: coresMax = load_field( _doc.get("coresMax"), union_of_None_type_or_inttype_or_strtype_or_ExpressionLoader, baseuri, loadingOptions, lc=_doc.get("coresMax") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `coresMax`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("coresMax") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `coresMax` field is not valid because:", SourceLine(_doc, "coresMax", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `coresMax` field is not valid because:", SourceLine(_doc, "coresMax", str), [e], detailed_message=f"the `coresMax` field with value `{val}` " "is not valid because:", ) ) ramMin = None if "ramMin" in _doc: try: ramMin = load_field( _doc.get("ramMin"), union_of_None_type_or_inttype_or_strtype_or_ExpressionLoader, baseuri, loadingOptions, lc=_doc.get("ramMin") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `ramMin`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("ramMin") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `ramMin` field is not valid because:", SourceLine(_doc, "ramMin", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `ramMin` field is not valid because:", SourceLine(_doc, "ramMin", str), [e], detailed_message=f"the `ramMin` field with value `{val}` " "is not valid because:", ) ) ramMax = None if "ramMax" in _doc: try: ramMax = load_field( _doc.get("ramMax"), union_of_None_type_or_inttype_or_strtype_or_ExpressionLoader, baseuri, loadingOptions, lc=_doc.get("ramMax") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `ramMax`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("ramMax") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `ramMax` field is not valid because:", SourceLine(_doc, "ramMax", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `ramMax` field is not valid because:", SourceLine(_doc, "ramMax", str), [e], detailed_message=f"the `ramMax` field with value `{val}` " "is not valid because:", ) ) tmpdirMin = None if "tmpdirMin" in _doc: try: tmpdirMin = load_field( _doc.get("tmpdirMin"), union_of_None_type_or_inttype_or_strtype_or_ExpressionLoader, baseuri, loadingOptions, lc=_doc.get("tmpdirMin") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `tmpdirMin`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("tmpdirMin") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `tmpdirMin` field is not valid because:", SourceLine(_doc, "tmpdirMin", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `tmpdirMin` field is not valid because:", SourceLine(_doc, "tmpdirMin", str), [e], detailed_message=f"the `tmpdirMin` field with value `{val}` " "is not valid because:", ) ) tmpdirMax = None if "tmpdirMax" in _doc: try: tmpdirMax = load_field( _doc.get("tmpdirMax"), union_of_None_type_or_inttype_or_strtype_or_ExpressionLoader, baseuri, loadingOptions, lc=_doc.get("tmpdirMax") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `tmpdirMax`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("tmpdirMax") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `tmpdirMax` field is not valid because:", SourceLine(_doc, "tmpdirMax", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `tmpdirMax` field is not valid because:", SourceLine(_doc, "tmpdirMax", str), [e], detailed_message=f"the `tmpdirMax` field with value `{val}` " "is not valid because:", ) ) outdirMin = None if "outdirMin" in _doc: try: outdirMin = load_field( _doc.get("outdirMin"), union_of_None_type_or_inttype_or_strtype_or_ExpressionLoader, baseuri, loadingOptions, lc=_doc.get("outdirMin") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `outdirMin`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("outdirMin") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `outdirMin` field is not valid because:", SourceLine(_doc, "outdirMin", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `outdirMin` field is not valid because:", SourceLine(_doc, "outdirMin", str), [e], detailed_message=f"the `outdirMin` field with value `{val}` " "is not valid because:", ) ) outdirMax = None if "outdirMax" in _doc: try: outdirMax = load_field( _doc.get("outdirMax"), union_of_None_type_or_inttype_or_strtype_or_ExpressionLoader, baseuri, loadingOptions, lc=_doc.get("outdirMax") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `outdirMax`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("outdirMax") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `outdirMax` field is not valid because:", SourceLine(_doc, "outdirMax", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `outdirMax` field is not valid because:", SourceLine(_doc, "outdirMax", str), [e], detailed_message=f"the `outdirMax` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `class`, `coresMin`, `coresMax`, `ramMin`, `ramMax`, `tmpdirMin`, `tmpdirMax`, `outdirMin`, `outdirMax`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( coresMin=coresMin, coresMax=coresMax, ramMin=ramMin, ramMax=ramMax, tmpdirMin=tmpdirMin, tmpdirMax=tmpdirMax, outdirMin=outdirMin, outdirMax=outdirMax, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.class_ is not None: uri = self.loadingOptions.vocab[self.class_] if p := self.loadingOptions.rvocab.get(uri[: -len(self.class_)]): uri = f"{p}:{self.class_}" else: uri = self.class_ u = save_relative_uri(uri, base_url, False, None, relative_uris) r["class"] = u if self.coresMin is not None: r["coresMin"] = save( self.coresMin, top=False, base_url=base_url, relative_uris=relative_uris ) if self.coresMax is not None: r["coresMax"] = save( self.coresMax, top=False, base_url=base_url, relative_uris=relative_uris ) if self.ramMin is not None: r["ramMin"] = save( self.ramMin, top=False, base_url=base_url, relative_uris=relative_uris ) if self.ramMax is not None: r["ramMax"] = save( self.ramMax, top=False, base_url=base_url, relative_uris=relative_uris ) if self.tmpdirMin is not None: r["tmpdirMin"] = save( self.tmpdirMin, top=False, base_url=base_url, relative_uris=relative_uris, ) if self.tmpdirMax is not None: r["tmpdirMax"] = save( self.tmpdirMax, top=False, base_url=base_url, relative_uris=relative_uris, ) if self.outdirMin is not None: r["outdirMin"] = save( self.outdirMin, top=False, base_url=base_url, relative_uris=relative_uris, ) if self.outdirMax is not None: r["outdirMax"] = save( self.outdirMax, top=False, base_url=base_url, relative_uris=relative_uris, ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset( [ "class", "coresMin", "coresMax", "ramMin", "ramMax", "tmpdirMin", "tmpdirMax", "outdirMin", "outdirMax", ] ) class ExpressionToolOutputParameter(OutputParameter): id: str def __init__( self, id: Any, label: Optional[Any] = None, secondaryFiles: Optional[Any] = None, streamable: Optional[Any] = None, doc: Optional[Any] = None, outputBinding: Optional[Any] = None, format: Optional[Any] = None, type_: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.label = label self.secondaryFiles = secondaryFiles self.streamable = streamable self.doc = doc self.id = id if id is not None else "_:" + str(_uuid__.uuid4()) self.outputBinding = outputBinding self.format = format self.type_ = type_ def __eq__(self, other: Any) -> bool: if isinstance(other, ExpressionToolOutputParameter): return bool( self.label == other.label and self.secondaryFiles == other.secondaryFiles and self.streamable == other.streamable and self.doc == other.doc and self.id == other.id and self.outputBinding == other.outputBinding and self.format == other.format and self.type_ == other.type_ ) return False def __hash__(self) -> int: return hash( ( self.label, self.secondaryFiles, self.streamable, self.doc, self.id, self.outputBinding, self.format, self.type_, ) ) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "ExpressionToolOutputParameter": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] id = None if "id" in _doc: try: id = load_field( _doc.get("id"), uri_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("id") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `id`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("id") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `id` field is not valid because:", SourceLine(_doc, "id", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `id` field is not valid because:", SourceLine(_doc, "id", str), [e], detailed_message=f"the `id` field with value `{val}` " "is not valid because:", ) ) __original_id_is_none = id is None if id is None: if docRoot is not None: id = docRoot else: _errors__.append(ValidationException("missing id")) if not __original_id_is_none: baseuri = cast(str, id) label = None if "label" in _doc: try: label = load_field( _doc.get("label"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("label") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `label`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("label") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [e], detailed_message=f"the `label` field with value `{val}` " "is not valid because:", ) ) secondaryFiles = None if "secondaryFiles" in _doc: try: secondaryFiles = load_field( _doc.get("secondaryFiles"), union_of_None_type_or_strtype_or_ExpressionLoader_or_array_of_union_of_strtype_or_ExpressionLoader, baseuri, loadingOptions, lc=_doc.get("secondaryFiles") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `secondaryFiles`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("secondaryFiles") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `secondaryFiles` field is not valid because:", SourceLine(_doc, "secondaryFiles", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `secondaryFiles` field is not valid because:", SourceLine(_doc, "secondaryFiles", str), [e], detailed_message=f"the `secondaryFiles` field with value `{val}` " "is not valid because:", ) ) streamable = None if "streamable" in _doc: try: streamable = load_field( _doc.get("streamable"), union_of_None_type_or_booltype, baseuri, loadingOptions, lc=_doc.get("streamable") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `streamable`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("streamable") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `streamable` field is not valid because:", SourceLine(_doc, "streamable", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `streamable` field is not valid because:", SourceLine(_doc, "streamable", str), [e], detailed_message=f"the `streamable` field with value `{val}` " "is not valid because:", ) ) doc = None if "doc" in _doc: try: doc = load_field( _doc.get("doc"), union_of_None_type_or_strtype_or_array_of_strtype, baseuri, loadingOptions, lc=_doc.get("doc") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `doc`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("doc") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [e], detailed_message=f"the `doc` field with value `{val}` " "is not valid because:", ) ) outputBinding = None if "outputBinding" in _doc: try: outputBinding = load_field( _doc.get("outputBinding"), union_of_None_type_or_CommandOutputBindingLoader, baseuri, loadingOptions, lc=_doc.get("outputBinding") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `outputBinding`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("outputBinding") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `outputBinding` field is not valid because:", SourceLine(_doc, "outputBinding", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `outputBinding` field is not valid because:", SourceLine(_doc, "outputBinding", str), [e], detailed_message=f"the `outputBinding` field with value `{val}` " "is not valid because:", ) ) format = None if "format" in _doc: try: format = load_field( _doc.get("format"), uri_union_of_None_type_or_strtype_or_ExpressionLoader_True_False_None_True, baseuri, loadingOptions, lc=_doc.get("format") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `format`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("format") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `format` field is not valid because:", SourceLine(_doc, "format", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `format` field is not valid because:", SourceLine(_doc, "format", str), [e], detailed_message=f"the `format` field with value `{val}` " "is not valid because:", ) ) type_ = None if "type" in _doc: try: type_ = load_field( _doc.get("type"), typedsl_union_of_None_type_or_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype_2, baseuri, loadingOptions, lc=_doc.get("type") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `type`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("type") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [e], detailed_message=f"the `type` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `label`, `secondaryFiles`, `streamable`, `doc`, `id`, `outputBinding`, `format`, `type`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( label=label, secondaryFiles=secondaryFiles, streamable=streamable, doc=doc, id=id, outputBinding=outputBinding, format=format, type_=type_, extension_fields=extension_fields, loadingOptions=loadingOptions, ) loadingOptions.idx[cast(str, id)] = (_constructed, loadingOptions) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.id is not None: u = save_relative_uri(self.id, base_url, True, None, relative_uris) r["id"] = u if self.label is not None: r["label"] = save( self.label, top=False, base_url=self.id, relative_uris=relative_uris ) if self.secondaryFiles is not None: r["secondaryFiles"] = save( self.secondaryFiles, top=False, base_url=self.id, relative_uris=relative_uris, ) if self.streamable is not None: r["streamable"] = save( self.streamable, top=False, base_url=self.id, relative_uris=relative_uris, ) if self.doc is not None: r["doc"] = save( self.doc, top=False, base_url=self.id, relative_uris=relative_uris ) if self.outputBinding is not None: r["outputBinding"] = save( self.outputBinding, top=False, base_url=self.id, relative_uris=relative_uris, ) if self.format is not None: u = save_relative_uri(self.format, self.id, True, None, relative_uris) r["format"] = u if self.type_ is not None: r["type"] = save( self.type_, top=False, base_url=self.id, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset( [ "label", "secondaryFiles", "streamable", "doc", "id", "outputBinding", "format", "type", ] ) class ExpressionTool(Process): """ Execute an expression as a Workflow step. """ id: str def __init__( self, inputs: Any, outputs: Any, expression: Any, id: Optional[Any] = None, requirements: Optional[Any] = None, hints: Optional[Any] = None, label: Optional[Any] = None, doc: Optional[Any] = None, cwlVersion: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.id = id if id is not None else "_:" + str(_uuid__.uuid4()) self.inputs = inputs self.outputs = outputs self.requirements = requirements self.hints = hints self.label = label self.doc = doc self.cwlVersion = cwlVersion self.class_ = "ExpressionTool" self.expression = expression def __eq__(self, other: Any) -> bool: if isinstance(other, ExpressionTool): return bool( self.id == other.id and self.inputs == other.inputs and self.outputs == other.outputs and self.requirements == other.requirements and self.hints == other.hints and self.label == other.label and self.doc == other.doc and self.cwlVersion == other.cwlVersion and self.class_ == other.class_ and self.expression == other.expression ) return False def __hash__(self) -> int: return hash( ( self.id, self.inputs, self.outputs, self.requirements, self.hints, self.label, self.doc, self.cwlVersion, self.class_, self.expression, ) ) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "ExpressionTool": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] id = None if "id" in _doc: try: id = load_field( _doc.get("id"), uri_union_of_None_type_or_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("id") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `id`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("id") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `id` field is not valid because:", SourceLine(_doc, "id", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `id` field is not valid because:", SourceLine(_doc, "id", str), [e], detailed_message=f"the `id` field with value `{val}` " "is not valid because:", ) ) __original_id_is_none = id is None if id is None: if docRoot is not None: id = docRoot else: id = "_:" + str(_uuid__.uuid4()) if not __original_id_is_none: baseuri = cast(str, id) try: if _doc.get("class") is None: raise ValidationException("missing required field `class`", None, []) class_ = load_field( _doc.get("class"), uri_ExpressionTool_classLoader_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("class") ) if class_ not in (cls.__name__, loadingOptions.vocab.get(cls.__name__)): raise ValidationException(f"tried `{cls.__name__}` but") except ValidationException as e: raise e try: if _doc.get("inputs") is None: raise ValidationException("missing required field `inputs`", None, []) inputs = load_field( _doc.get("inputs"), idmap_inputs_array_of_InputParameterLoader, baseuri, loadingOptions, lc=_doc.get("inputs") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `inputs`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("inputs") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `inputs` field is not valid because:", SourceLine(_doc, "inputs", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `inputs` field is not valid because:", SourceLine(_doc, "inputs", str), [e], detailed_message=f"the `inputs` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("outputs") is None: raise ValidationException("missing required field `outputs`", None, []) outputs = load_field( _doc.get("outputs"), idmap_outputs_array_of_ExpressionToolOutputParameterLoader, baseuri, loadingOptions, lc=_doc.get("outputs") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `outputs`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("outputs") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `outputs` field is not valid because:", SourceLine(_doc, "outputs", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `outputs` field is not valid because:", SourceLine(_doc, "outputs", str), [e], detailed_message=f"the `outputs` field with value `{val}` " "is not valid because:", ) ) requirements = None if "requirements" in _doc: try: requirements = load_field( _doc.get("requirements"), idmap_requirements_union_of_None_type_or_array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader_or_LoadListingRequirementLoader_or_InplaceUpdateRequirementLoader_or_SecretsLoader_or_TimeLimitLoader_or_WorkReuseLoader_or_NetworkAccessLoader_or_MPIRequirementLoader_or_CUDARequirementLoader_or_ShmSizeLoader, baseuri, loadingOptions, lc=_doc.get("requirements") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `requirements`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("requirements") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `requirements` field is not valid because:", SourceLine(_doc, "requirements", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `requirements` field is not valid because:", SourceLine(_doc, "requirements", str), [e], detailed_message=f"the `requirements` field with value `{val}` " "is not valid because:", ) ) hints = None if "hints" in _doc: try: hints = load_field( _doc.get("hints"), idmap_hints_union_of_None_type_or_array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader_or_LoadListingRequirementLoader_or_InplaceUpdateRequirementLoader_or_SecretsLoader_or_TimeLimitLoader_or_WorkReuseLoader_or_NetworkAccessLoader_or_MPIRequirementLoader_or_CUDARequirementLoader_or_ShmSizeLoader_or_Any_type, baseuri, loadingOptions, lc=_doc.get("hints") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `hints`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("hints") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `hints` field is not valid because:", SourceLine(_doc, "hints", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `hints` field is not valid because:", SourceLine(_doc, "hints", str), [e], detailed_message=f"the `hints` field with value `{val}` " "is not valid because:", ) ) label = None if "label" in _doc: try: label = load_field( _doc.get("label"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("label") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `label`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("label") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [e], detailed_message=f"the `label` field with value `{val}` " "is not valid because:", ) ) doc = None if "doc" in _doc: try: doc = load_field( _doc.get("doc"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("doc") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `doc`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("doc") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [e], detailed_message=f"the `doc` field with value `{val}` " "is not valid because:", ) ) cwlVersion = None if "cwlVersion" in _doc: try: cwlVersion = load_field( _doc.get("cwlVersion"), uri_union_of_None_type_or_CWLVersionLoader_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("cwlVersion") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `cwlVersion`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("cwlVersion") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `cwlVersion` field is not valid because:", SourceLine(_doc, "cwlVersion", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `cwlVersion` field is not valid because:", SourceLine(_doc, "cwlVersion", str), [e], detailed_message=f"the `cwlVersion` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("expression") is None: raise ValidationException("missing required field `expression`", None, []) expression = load_field( _doc.get("expression"), union_of_strtype_or_ExpressionLoader, baseuri, loadingOptions, lc=_doc.get("expression") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `expression`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("expression") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `expression` field is not valid because:", SourceLine(_doc, "expression", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `expression` field is not valid because:", SourceLine(_doc, "expression", str), [e], detailed_message=f"the `expression` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `id`, `inputs`, `outputs`, `requirements`, `hints`, `label`, `doc`, `cwlVersion`, `class`, `expression`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( id=id, inputs=inputs, outputs=outputs, requirements=requirements, hints=hints, label=label, doc=doc, cwlVersion=cwlVersion, expression=expression, extension_fields=extension_fields, loadingOptions=loadingOptions, ) loadingOptions.idx[cast(str, id)] = (_constructed, loadingOptions) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.id is not None: u = save_relative_uri(self.id, base_url, True, None, relative_uris) r["id"] = u if self.class_ is not None: uri = self.loadingOptions.vocab[self.class_] if p := self.loadingOptions.rvocab.get(uri[: -len(self.class_)]): uri = f"{p}:{self.class_}" else: uri = self.class_ u = save_relative_uri(uri, self.id, False, None, relative_uris) r["class"] = u if self.inputs is not None: r["inputs"] = save( self.inputs, top=False, base_url=self.id, relative_uris=relative_uris ) if self.outputs is not None: r["outputs"] = save( self.outputs, top=False, base_url=self.id, relative_uris=relative_uris ) if self.requirements is not None: r["requirements"] = save( self.requirements, top=False, base_url=self.id, relative_uris=relative_uris, ) if self.hints is not None: r["hints"] = save( self.hints, top=False, base_url=self.id, relative_uris=relative_uris ) if self.label is not None: r["label"] = save( self.label, top=False, base_url=self.id, relative_uris=relative_uris ) if self.doc is not None: r["doc"] = save( self.doc, top=False, base_url=self.id, relative_uris=relative_uris ) if self.cwlVersion is not None: u = save_relative_uri(self.cwlVersion, self.id, False, None, relative_uris) r["cwlVersion"] = u if self.expression is not None: r["expression"] = save( self.expression, top=False, base_url=self.id, relative_uris=relative_uris, ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset( [ "id", "inputs", "outputs", "requirements", "hints", "label", "doc", "cwlVersion", "class", "expression", ] ) class WorkflowOutputParameter(OutputParameter): """ Describe an output parameter of a workflow. The parameter must be connected to one or more parameters defined in the workflow that will provide the value of the output parameter. """ id: str def __init__( self, id: Any, label: Optional[Any] = None, secondaryFiles: Optional[Any] = None, streamable: Optional[Any] = None, doc: Optional[Any] = None, outputBinding: Optional[Any] = None, format: Optional[Any] = None, outputSource: Optional[Any] = None, linkMerge: Optional[Any] = None, type_: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.label = label self.secondaryFiles = secondaryFiles self.streamable = streamable self.doc = doc self.id = id if id is not None else "_:" + str(_uuid__.uuid4()) self.outputBinding = outputBinding self.format = format self.outputSource = outputSource self.linkMerge = linkMerge self.type_ = type_ def __eq__(self, other: Any) -> bool: if isinstance(other, WorkflowOutputParameter): return bool( self.label == other.label and self.secondaryFiles == other.secondaryFiles and self.streamable == other.streamable and self.doc == other.doc and self.id == other.id and self.outputBinding == other.outputBinding and self.format == other.format and self.outputSource == other.outputSource and self.linkMerge == other.linkMerge and self.type_ == other.type_ ) return False def __hash__(self) -> int: return hash( ( self.label, self.secondaryFiles, self.streamable, self.doc, self.id, self.outputBinding, self.format, self.outputSource, self.linkMerge, self.type_, ) ) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "WorkflowOutputParameter": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] id = None if "id" in _doc: try: id = load_field( _doc.get("id"), uri_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("id") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `id`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("id") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `id` field is not valid because:", SourceLine(_doc, "id", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `id` field is not valid because:", SourceLine(_doc, "id", str), [e], detailed_message=f"the `id` field with value `{val}` " "is not valid because:", ) ) __original_id_is_none = id is None if id is None: if docRoot is not None: id = docRoot else: _errors__.append(ValidationException("missing id")) if not __original_id_is_none: baseuri = cast(str, id) label = None if "label" in _doc: try: label = load_field( _doc.get("label"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("label") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `label`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("label") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [e], detailed_message=f"the `label` field with value `{val}` " "is not valid because:", ) ) secondaryFiles = None if "secondaryFiles" in _doc: try: secondaryFiles = load_field( _doc.get("secondaryFiles"), union_of_None_type_or_strtype_or_ExpressionLoader_or_array_of_union_of_strtype_or_ExpressionLoader, baseuri, loadingOptions, lc=_doc.get("secondaryFiles") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `secondaryFiles`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("secondaryFiles") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `secondaryFiles` field is not valid because:", SourceLine(_doc, "secondaryFiles", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `secondaryFiles` field is not valid because:", SourceLine(_doc, "secondaryFiles", str), [e], detailed_message=f"the `secondaryFiles` field with value `{val}` " "is not valid because:", ) ) streamable = None if "streamable" in _doc: try: streamable = load_field( _doc.get("streamable"), union_of_None_type_or_booltype, baseuri, loadingOptions, lc=_doc.get("streamable") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `streamable`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("streamable") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `streamable` field is not valid because:", SourceLine(_doc, "streamable", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `streamable` field is not valid because:", SourceLine(_doc, "streamable", str), [e], detailed_message=f"the `streamable` field with value `{val}` " "is not valid because:", ) ) doc = None if "doc" in _doc: try: doc = load_field( _doc.get("doc"), union_of_None_type_or_strtype_or_array_of_strtype, baseuri, loadingOptions, lc=_doc.get("doc") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `doc`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("doc") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [e], detailed_message=f"the `doc` field with value `{val}` " "is not valid because:", ) ) outputBinding = None if "outputBinding" in _doc: try: outputBinding = load_field( _doc.get("outputBinding"), union_of_None_type_or_CommandOutputBindingLoader, baseuri, loadingOptions, lc=_doc.get("outputBinding") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `outputBinding`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("outputBinding") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `outputBinding` field is not valid because:", SourceLine(_doc, "outputBinding", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `outputBinding` field is not valid because:", SourceLine(_doc, "outputBinding", str), [e], detailed_message=f"the `outputBinding` field with value `{val}` " "is not valid because:", ) ) format = None if "format" in _doc: try: format = load_field( _doc.get("format"), uri_union_of_None_type_or_strtype_or_ExpressionLoader_True_False_None_True, baseuri, loadingOptions, lc=_doc.get("format") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `format`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("format") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `format` field is not valid because:", SourceLine(_doc, "format", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `format` field is not valid because:", SourceLine(_doc, "format", str), [e], detailed_message=f"the `format` field with value `{val}` " "is not valid because:", ) ) outputSource = None if "outputSource" in _doc: try: outputSource = load_field( _doc.get("outputSource"), uri_union_of_None_type_or_strtype_or_array_of_strtype_False_False_1_None, baseuri, loadingOptions, lc=_doc.get("outputSource") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `outputSource`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("outputSource") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `outputSource` field is not valid because:", SourceLine(_doc, "outputSource", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `outputSource` field is not valid because:", SourceLine(_doc, "outputSource", str), [e], detailed_message=f"the `outputSource` field with value `{val}` " "is not valid because:", ) ) linkMerge = None if "linkMerge" in _doc: try: linkMerge = load_field( _doc.get("linkMerge"), union_of_None_type_or_LinkMergeMethodLoader, baseuri, loadingOptions, lc=_doc.get("linkMerge") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `linkMerge`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("linkMerge") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `linkMerge` field is not valid because:", SourceLine(_doc, "linkMerge", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `linkMerge` field is not valid because:", SourceLine(_doc, "linkMerge", str), [e], detailed_message=f"the `linkMerge` field with value `{val}` " "is not valid because:", ) ) type_ = None if "type" in _doc: try: type_ = load_field( _doc.get("type"), typedsl_union_of_None_type_or_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype_2, baseuri, loadingOptions, lc=_doc.get("type") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `type`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("type") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [e], detailed_message=f"the `type` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `label`, `secondaryFiles`, `streamable`, `doc`, `id`, `outputBinding`, `format`, `outputSource`, `linkMerge`, `type`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( label=label, secondaryFiles=secondaryFiles, streamable=streamable, doc=doc, id=id, outputBinding=outputBinding, format=format, outputSource=outputSource, linkMerge=linkMerge, type_=type_, extension_fields=extension_fields, loadingOptions=loadingOptions, ) loadingOptions.idx[cast(str, id)] = (_constructed, loadingOptions) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.id is not None: u = save_relative_uri(self.id, base_url, True, None, relative_uris) r["id"] = u if self.label is not None: r["label"] = save( self.label, top=False, base_url=self.id, relative_uris=relative_uris ) if self.secondaryFiles is not None: r["secondaryFiles"] = save( self.secondaryFiles, top=False, base_url=self.id, relative_uris=relative_uris, ) if self.streamable is not None: r["streamable"] = save( self.streamable, top=False, base_url=self.id, relative_uris=relative_uris, ) if self.doc is not None: r["doc"] = save( self.doc, top=False, base_url=self.id, relative_uris=relative_uris ) if self.outputBinding is not None: r["outputBinding"] = save( self.outputBinding, top=False, base_url=self.id, relative_uris=relative_uris, ) if self.format is not None: u = save_relative_uri(self.format, self.id, True, None, relative_uris) r["format"] = u if self.outputSource is not None: u = save_relative_uri(self.outputSource, self.id, False, 1, relative_uris) r["outputSource"] = u if self.linkMerge is not None: r["linkMerge"] = save( self.linkMerge, top=False, base_url=self.id, relative_uris=relative_uris ) if self.type_ is not None: r["type"] = save( self.type_, top=False, base_url=self.id, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset( [ "label", "secondaryFiles", "streamable", "doc", "id", "outputBinding", "format", "outputSource", "linkMerge", "type", ] ) class Sink(Saveable): pass class WorkflowStepInput(Sink): """ The input of a workflow step connects an upstream parameter (from the workflow inputs, or the outputs of other workflows steps) with the input parameters of the underlying step. ## Input object A WorkflowStepInput object must contain an `id` field in the form `#fieldname` or `#prefix/fieldname`. When the `id` field contains a slash `/` the field name consists of the characters following the final slash (the prefix portion may contain one or more slashes to indicate scope). This defines a field of the workflow step input object with the value of the `source` parameter(s). ## Merging To merge multiple inbound data links, [MultipleInputFeatureRequirement](#MultipleInputFeatureRequirement) must be specified in the workflow or workflow step requirements. If the sink parameter is an array, or named in a [workflow scatter](#WorkflowStep) operation, there may be multiple inbound data links listed in the `source` field. The values from the input links are merged depending on the method specified in the `linkMerge` field. If not specified, the default method is "merge_nested". * **merge_nested** The input must be an array consisting of exactly one entry for each input link. If "merge_nested" is specified with a single link, the value from the link must be wrapped in a single-item list. * **merge_flattened** 1. The source and sink parameters must be compatible types, or the source type must be compatible with single element from the "items" type of the destination array parameter. 2. Source parameters which are arrays are concatenated. Source parameters which are single element types are appended as single elements. """ id: str def __init__( self, id: Any, source: Optional[Any] = None, linkMerge: Optional[Any] = None, default: Optional[Any] = None, valueFrom: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.source = source self.linkMerge = linkMerge self.id = id if id is not None else "_:" + str(_uuid__.uuid4()) self.default = default self.valueFrom = valueFrom def __eq__(self, other: Any) -> bool: if isinstance(other, WorkflowStepInput): return bool( self.source == other.source and self.linkMerge == other.linkMerge and self.id == other.id and self.default == other.default and self.valueFrom == other.valueFrom ) return False def __hash__(self) -> int: return hash( (self.source, self.linkMerge, self.id, self.default, self.valueFrom) ) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "WorkflowStepInput": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] id = None if "id" in _doc: try: id = load_field( _doc.get("id"), uri_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("id") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `id`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("id") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `id` field is not valid because:", SourceLine(_doc, "id", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `id` field is not valid because:", SourceLine(_doc, "id", str), [e], detailed_message=f"the `id` field with value `{val}` " "is not valid because:", ) ) __original_id_is_none = id is None if id is None: if docRoot is not None: id = docRoot else: _errors__.append(ValidationException("missing id")) if not __original_id_is_none: baseuri = cast(str, id) source = None if "source" in _doc: try: source = load_field( _doc.get("source"), uri_union_of_None_type_or_strtype_or_array_of_strtype_False_False_2_None, baseuri, loadingOptions, lc=_doc.get("source") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `source`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("source") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `source` field is not valid because:", SourceLine(_doc, "source", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `source` field is not valid because:", SourceLine(_doc, "source", str), [e], detailed_message=f"the `source` field with value `{val}` " "is not valid because:", ) ) linkMerge = None if "linkMerge" in _doc: try: linkMerge = load_field( _doc.get("linkMerge"), union_of_None_type_or_LinkMergeMethodLoader, baseuri, loadingOptions, lc=_doc.get("linkMerge") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `linkMerge`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("linkMerge") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `linkMerge` field is not valid because:", SourceLine(_doc, "linkMerge", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `linkMerge` field is not valid because:", SourceLine(_doc, "linkMerge", str), [e], detailed_message=f"the `linkMerge` field with value `{val}` " "is not valid because:", ) ) default = None if "default" in _doc: try: default = load_field( _doc.get("default"), union_of_None_type_or_CWLObjectTypeLoader, baseuri, loadingOptions, lc=_doc.get("default") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `default`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("default") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `default` field is not valid because:", SourceLine(_doc, "default", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `default` field is not valid because:", SourceLine(_doc, "default", str), [e], detailed_message=f"the `default` field with value `{val}` " "is not valid because:", ) ) valueFrom = None if "valueFrom" in _doc: try: valueFrom = load_field( _doc.get("valueFrom"), union_of_None_type_or_strtype_or_ExpressionLoader, baseuri, loadingOptions, lc=_doc.get("valueFrom") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `valueFrom`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("valueFrom") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `valueFrom` field is not valid because:", SourceLine(_doc, "valueFrom", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `valueFrom` field is not valid because:", SourceLine(_doc, "valueFrom", str), [e], detailed_message=f"the `valueFrom` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `source`, `linkMerge`, `id`, `default`, `valueFrom`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( source=source, linkMerge=linkMerge, id=id, default=default, valueFrom=valueFrom, extension_fields=extension_fields, loadingOptions=loadingOptions, ) loadingOptions.idx[cast(str, id)] = (_constructed, loadingOptions) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.id is not None: u = save_relative_uri(self.id, base_url, True, None, relative_uris) r["id"] = u if self.source is not None: u = save_relative_uri(self.source, self.id, False, 2, relative_uris) r["source"] = u if self.linkMerge is not None: r["linkMerge"] = save( self.linkMerge, top=False, base_url=self.id, relative_uris=relative_uris ) if self.default is not None: r["default"] = save( self.default, top=False, base_url=self.id, relative_uris=relative_uris ) if self.valueFrom is not None: r["valueFrom"] = save( self.valueFrom, top=False, base_url=self.id, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["source", "linkMerge", "id", "default", "valueFrom"]) class WorkflowStepOutput(Saveable): """ Associate an output parameter of the underlying process with a workflow parameter. The workflow parameter (given in the `id` field) be may be used as a `source` to connect with input parameters of other workflow steps, or with an output parameter of the process. """ id: str def __init__( self, id: Any, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.id = id if id is not None else "_:" + str(_uuid__.uuid4()) def __eq__(self, other: Any) -> bool: if isinstance(other, WorkflowStepOutput): return bool(self.id == other.id) return False def __hash__(self) -> int: return hash((self.id)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "WorkflowStepOutput": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] id = None if "id" in _doc: try: id = load_field( _doc.get("id"), uri_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("id") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `id`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("id") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `id` field is not valid because:", SourceLine(_doc, "id", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `id` field is not valid because:", SourceLine(_doc, "id", str), [e], detailed_message=f"the `id` field with value `{val}` " "is not valid because:", ) ) __original_id_is_none = id is None if id is None: if docRoot is not None: id = docRoot else: _errors__.append(ValidationException("missing id")) if not __original_id_is_none: baseuri = cast(str, id) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `id`".format(k), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( id=id, extension_fields=extension_fields, loadingOptions=loadingOptions, ) loadingOptions.idx[cast(str, id)] = (_constructed, loadingOptions) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.id is not None: u = save_relative_uri(self.id, base_url, True, None, relative_uris) r["id"] = u # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["id"]) class WorkflowStep(Saveable): """ A workflow step is an executable element of a workflow. It specifies the underlying process implementation (such as `CommandLineTool` or another `Workflow`) in the `run` field and connects the input and output parameters of the underlying process to workflow parameters. # Scatter/gather To use scatter/gather, [ScatterFeatureRequirement](#ScatterFeatureRequirement) must be specified in the workflow or workflow step requirements. A "scatter" operation specifies that the associated workflow step or subworkflow should execute separately over a list of input elements. Each job making up a scatter operation is independent and may be executed concurrently. The `scatter` field specifies one or more input parameters which will be scattered. An input parameter may be listed more than once. The declared type of each input parameter is implicitly becomes an array of items of the input parameter type. If a parameter is listed more than once, it becomes a nested array. As a result, upstream parameters which are connected to scattered parameters must be arrays. All output parameter types are also implicitly wrapped in arrays. Each job in the scatter results in an entry in the output array. If any scattered parameter runtime value is an empty array, all outputs are set to empty arrays and no work is done for the step, according to applicable scattering rules. If `scatter` declares more than one input parameter, `scatterMethod` describes how to decompose the input into a discrete set of jobs. * **dotproduct** specifies that each of the input arrays are aligned and one element taken from each array to construct each job. It is an error if all input arrays are not the same length. * **nested_crossproduct** specifies the Cartesian product of the inputs, producing a job for every combination of the scattered inputs. The output must be nested arrays for each level of scattering, in the order that the input arrays are listed in the `scatter` field. * **flat_crossproduct** specifies the Cartesian product of the inputs, producing a job for every combination of the scattered inputs. The output arrays must be flattened to a single level, but otherwise listed in the order that the input arrays are listed in the `scatter` field. # Subworkflows To specify a nested workflow as part of a workflow step, [SubworkflowFeatureRequirement](#SubworkflowFeatureRequirement) must be specified in the workflow or workflow step requirements. It is a fatal error if a workflow directly or indirectly invokes itself as a subworkflow (recursive workflows are not allowed). """ id: str def __init__( self, id: Any, in_: Any, out: Any, run: Any, requirements: Optional[Any] = None, hints: Optional[Any] = None, label: Optional[Any] = None, doc: Optional[Any] = None, scatter: Optional[Any] = None, scatterMethod: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.id = id if id is not None else "_:" + str(_uuid__.uuid4()) self.in_ = in_ self.out = out self.requirements = requirements self.hints = hints self.label = label self.doc = doc self.run = run self.scatter = scatter self.scatterMethod = scatterMethod def __eq__(self, other: Any) -> bool: if isinstance(other, WorkflowStep): return bool( self.id == other.id and self.in_ == other.in_ and self.out == other.out and self.requirements == other.requirements and self.hints == other.hints and self.label == other.label and self.doc == other.doc and self.run == other.run and self.scatter == other.scatter and self.scatterMethod == other.scatterMethod ) return False def __hash__(self) -> int: return hash( ( self.id, self.in_, self.out, self.requirements, self.hints, self.label, self.doc, self.run, self.scatter, self.scatterMethod, ) ) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "WorkflowStep": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] id = None if "id" in _doc: try: id = load_field( _doc.get("id"), uri_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("id") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `id`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("id") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `id` field is not valid because:", SourceLine(_doc, "id", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `id` field is not valid because:", SourceLine(_doc, "id", str), [e], detailed_message=f"the `id` field with value `{val}` " "is not valid because:", ) ) __original_id_is_none = id is None if id is None: if docRoot is not None: id = docRoot else: _errors__.append(ValidationException("missing id")) if not __original_id_is_none: baseuri = cast(str, id) try: if _doc.get("in") is None: raise ValidationException("missing required field `in`", None, []) in_ = load_field( _doc.get("in"), idmap_in__array_of_WorkflowStepInputLoader, baseuri, loadingOptions, lc=_doc.get("in") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `in`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("in") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `in` field is not valid because:", SourceLine(_doc, "in", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `in` field is not valid because:", SourceLine(_doc, "in", str), [e], detailed_message=f"the `in` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("out") is None: raise ValidationException("missing required field `out`", None, []) out = load_field( _doc.get("out"), uri_union_of_array_of_union_of_strtype_or_WorkflowStepOutputLoader_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("out") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `out`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("out") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `out` field is not valid because:", SourceLine(_doc, "out", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `out` field is not valid because:", SourceLine(_doc, "out", str), [e], detailed_message=f"the `out` field with value `{val}` " "is not valid because:", ) ) requirements = None if "requirements" in _doc: try: requirements = load_field( _doc.get("requirements"), idmap_requirements_union_of_None_type_or_array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader_or_LoadListingRequirementLoader_or_InplaceUpdateRequirementLoader_or_SecretsLoader_or_TimeLimitLoader_or_WorkReuseLoader_or_NetworkAccessLoader_or_MPIRequirementLoader_or_CUDARequirementLoader_or_ShmSizeLoader, baseuri, loadingOptions, lc=_doc.get("requirements") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `requirements`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("requirements") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `requirements` field is not valid because:", SourceLine(_doc, "requirements", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `requirements` field is not valid because:", SourceLine(_doc, "requirements", str), [e], detailed_message=f"the `requirements` field with value `{val}` " "is not valid because:", ) ) hints = None if "hints" in _doc: try: hints = load_field( _doc.get("hints"), idmap_hints_union_of_None_type_or_array_of_Any_type, baseuri, loadingOptions, lc=_doc.get("hints") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `hints`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("hints") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `hints` field is not valid because:", SourceLine(_doc, "hints", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `hints` field is not valid because:", SourceLine(_doc, "hints", str), [e], detailed_message=f"the `hints` field with value `{val}` " "is not valid because:", ) ) label = None if "label" in _doc: try: label = load_field( _doc.get("label"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("label") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `label`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("label") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [e], detailed_message=f"the `label` field with value `{val}` " "is not valid because:", ) ) doc = None if "doc" in _doc: try: doc = load_field( _doc.get("doc"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("doc") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `doc`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("doc") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [e], detailed_message=f"the `doc` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("run") is None: raise ValidationException("missing required field `run`", None, []) run = load_field( _doc.get("run"), uri_union_of_strtype_or_CommandLineToolLoader_or_ExpressionToolLoader_or_WorkflowLoader_or_ProcessGeneratorLoader_False_False_None_None, baseuri, loadingOptions, lc=_doc.get("run") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `run`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("run") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `run` field is not valid because:", SourceLine(_doc, "run", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `run` field is not valid because:", SourceLine(_doc, "run", str), [e], detailed_message=f"the `run` field with value `{val}` " "is not valid because:", ) ) scatter = None if "scatter" in _doc: try: scatter = load_field( _doc.get("scatter"), uri_union_of_None_type_or_strtype_or_array_of_strtype_False_False_0_None, baseuri, loadingOptions, lc=_doc.get("scatter") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `scatter`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("scatter") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `scatter` field is not valid because:", SourceLine(_doc, "scatter", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `scatter` field is not valid because:", SourceLine(_doc, "scatter", str), [e], detailed_message=f"the `scatter` field with value `{val}` " "is not valid because:", ) ) scatterMethod = None if "scatterMethod" in _doc: try: scatterMethod = load_field( _doc.get("scatterMethod"), uri_union_of_None_type_or_ScatterMethodLoader_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("scatterMethod") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `scatterMethod`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("scatterMethod") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `scatterMethod` field is not valid because:", SourceLine(_doc, "scatterMethod", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `scatterMethod` field is not valid because:", SourceLine(_doc, "scatterMethod", str), [e], detailed_message=f"the `scatterMethod` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `id`, `in`, `out`, `requirements`, `hints`, `label`, `doc`, `run`, `scatter`, `scatterMethod`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( id=id, in_=in_, out=out, requirements=requirements, hints=hints, label=label, doc=doc, run=run, scatter=scatter, scatterMethod=scatterMethod, extension_fields=extension_fields, loadingOptions=loadingOptions, ) loadingOptions.idx[cast(str, id)] = (_constructed, loadingOptions) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.id is not None: u = save_relative_uri(self.id, base_url, True, None, relative_uris) r["id"] = u if self.in_ is not None: r["in"] = save( self.in_, top=False, base_url=self.id, relative_uris=relative_uris ) if self.out is not None: u = save_relative_uri(self.out, self.id, True, None, relative_uris) r["out"] = u if self.requirements is not None: r["requirements"] = save( self.requirements, top=False, base_url=self.id, relative_uris=relative_uris, ) if self.hints is not None: r["hints"] = save( self.hints, top=False, base_url=self.id, relative_uris=relative_uris ) if self.label is not None: r["label"] = save( self.label, top=False, base_url=self.id, relative_uris=relative_uris ) if self.doc is not None: r["doc"] = save( self.doc, top=False, base_url=self.id, relative_uris=relative_uris ) if self.run is not None: u = save_relative_uri(self.run, self.id, False, None, relative_uris) r["run"] = u if self.scatter is not None: u = save_relative_uri(self.scatter, self.id, False, 0, relative_uris) r["scatter"] = u if self.scatterMethod is not None: u = save_relative_uri( self.scatterMethod, self.id, False, None, relative_uris ) r["scatterMethod"] = u # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset( [ "id", "in", "out", "requirements", "hints", "label", "doc", "run", "scatter", "scatterMethod", ] ) class Workflow(Process): """ A workflow describes a set of **steps** and the **dependencies** between those steps. When a step produces output that will be consumed by a second step, the first step is a dependency of the second step. When there is a dependency, the workflow engine must execute the preceding step and wait for it to successfully produce output before executing the dependent step. If two steps are defined in the workflow graph that are not directly or indirectly dependent, these steps are **independent**, and may execute in any order or execute concurrently. A workflow is complete when all steps have been executed. Dependencies between parameters are expressed using the `source` field on [workflow step input parameters](#WorkflowStepInput) and [workflow output parameters](#WorkflowOutputParameter). The `source` field expresses the dependency of one parameter on another such that when a value is associated with the parameter specified by `source`, that value is propagated to the destination parameter. When all data links inbound to a given step are fufilled, the step is ready to execute. ## Workflow success and failure A completed step must result in one of `success`, `temporaryFailure` or `permanentFailure` states. An implementation may choose to retry a step execution which resulted in `temporaryFailure`. An implementation may choose to either continue running other steps of a workflow, or terminate immediately upon `permanentFailure`. * If any step of a workflow execution results in `permanentFailure`, then the workflow status is `permanentFailure`. * If one or more steps result in `temporaryFailure` and all other steps complete `success` or are not executed, then the workflow status is `temporaryFailure`. * If all workflow steps are executed and complete with `success`, then the workflow status is `success`. # Extensions [ScatterFeatureRequirement](#ScatterFeatureRequirement) and [SubworkflowFeatureRequirement](#SubworkflowFeatureRequirement) are available as standard [extensions](#Extensions_and_Metadata) to core workflow semantics. """ id: str def __init__( self, inputs: Any, outputs: Any, steps: Any, id: Optional[Any] = None, requirements: Optional[Any] = None, hints: Optional[Any] = None, label: Optional[Any] = None, doc: Optional[Any] = None, cwlVersion: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.id = id if id is not None else "_:" + str(_uuid__.uuid4()) self.inputs = inputs self.outputs = outputs self.requirements = requirements self.hints = hints self.label = label self.doc = doc self.cwlVersion = cwlVersion self.class_ = "Workflow" self.steps = steps def __eq__(self, other: Any) -> bool: if isinstance(other, Workflow): return bool( self.id == other.id and self.inputs == other.inputs and self.outputs == other.outputs and self.requirements == other.requirements and self.hints == other.hints and self.label == other.label and self.doc == other.doc and self.cwlVersion == other.cwlVersion and self.class_ == other.class_ and self.steps == other.steps ) return False def __hash__(self) -> int: return hash( ( self.id, self.inputs, self.outputs, self.requirements, self.hints, self.label, self.doc, self.cwlVersion, self.class_, self.steps, ) ) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "Workflow": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] id = None if "id" in _doc: try: id = load_field( _doc.get("id"), uri_union_of_None_type_or_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("id") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `id`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("id") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `id` field is not valid because:", SourceLine(_doc, "id", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `id` field is not valid because:", SourceLine(_doc, "id", str), [e], detailed_message=f"the `id` field with value `{val}` " "is not valid because:", ) ) __original_id_is_none = id is None if id is None: if docRoot is not None: id = docRoot else: id = "_:" + str(_uuid__.uuid4()) if not __original_id_is_none: baseuri = cast(str, id) try: if _doc.get("class") is None: raise ValidationException("missing required field `class`", None, []) class_ = load_field( _doc.get("class"), uri_Workflow_classLoader_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("class") ) if class_ not in (cls.__name__, loadingOptions.vocab.get(cls.__name__)): raise ValidationException(f"tried `{cls.__name__}` but") except ValidationException as e: raise e try: if _doc.get("inputs") is None: raise ValidationException("missing required field `inputs`", None, []) inputs = load_field( _doc.get("inputs"), idmap_inputs_array_of_InputParameterLoader, baseuri, loadingOptions, lc=_doc.get("inputs") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `inputs`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("inputs") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `inputs` field is not valid because:", SourceLine(_doc, "inputs", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `inputs` field is not valid because:", SourceLine(_doc, "inputs", str), [e], detailed_message=f"the `inputs` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("outputs") is None: raise ValidationException("missing required field `outputs`", None, []) outputs = load_field( _doc.get("outputs"), idmap_outputs_array_of_WorkflowOutputParameterLoader, baseuri, loadingOptions, lc=_doc.get("outputs") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `outputs`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("outputs") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `outputs` field is not valid because:", SourceLine(_doc, "outputs", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `outputs` field is not valid because:", SourceLine(_doc, "outputs", str), [e], detailed_message=f"the `outputs` field with value `{val}` " "is not valid because:", ) ) requirements = None if "requirements" in _doc: try: requirements = load_field( _doc.get("requirements"), idmap_requirements_union_of_None_type_or_array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader_or_LoadListingRequirementLoader_or_InplaceUpdateRequirementLoader_or_SecretsLoader_or_TimeLimitLoader_or_WorkReuseLoader_or_NetworkAccessLoader_or_MPIRequirementLoader_or_CUDARequirementLoader_or_ShmSizeLoader, baseuri, loadingOptions, lc=_doc.get("requirements") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `requirements`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("requirements") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `requirements` field is not valid because:", SourceLine(_doc, "requirements", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `requirements` field is not valid because:", SourceLine(_doc, "requirements", str), [e], detailed_message=f"the `requirements` field with value `{val}` " "is not valid because:", ) ) hints = None if "hints" in _doc: try: hints = load_field( _doc.get("hints"), idmap_hints_union_of_None_type_or_array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader_or_LoadListingRequirementLoader_or_InplaceUpdateRequirementLoader_or_SecretsLoader_or_TimeLimitLoader_or_WorkReuseLoader_or_NetworkAccessLoader_or_MPIRequirementLoader_or_CUDARequirementLoader_or_ShmSizeLoader_or_Any_type, baseuri, loadingOptions, lc=_doc.get("hints") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `hints`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("hints") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `hints` field is not valid because:", SourceLine(_doc, "hints", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `hints` field is not valid because:", SourceLine(_doc, "hints", str), [e], detailed_message=f"the `hints` field with value `{val}` " "is not valid because:", ) ) label = None if "label" in _doc: try: label = load_field( _doc.get("label"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("label") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `label`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("label") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [e], detailed_message=f"the `label` field with value `{val}` " "is not valid because:", ) ) doc = None if "doc" in _doc: try: doc = load_field( _doc.get("doc"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("doc") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `doc`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("doc") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [e], detailed_message=f"the `doc` field with value `{val}` " "is not valid because:", ) ) cwlVersion = None if "cwlVersion" in _doc: try: cwlVersion = load_field( _doc.get("cwlVersion"), uri_union_of_None_type_or_CWLVersionLoader_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("cwlVersion") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `cwlVersion`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("cwlVersion") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `cwlVersion` field is not valid because:", SourceLine(_doc, "cwlVersion", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `cwlVersion` field is not valid because:", SourceLine(_doc, "cwlVersion", str), [e], detailed_message=f"the `cwlVersion` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("steps") is None: raise ValidationException("missing required field `steps`", None, []) steps = load_field( _doc.get("steps"), idmap_steps_union_of_array_of_WorkflowStepLoader, baseuri, loadingOptions, lc=_doc.get("steps") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `steps`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("steps") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `steps` field is not valid because:", SourceLine(_doc, "steps", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `steps` field is not valid because:", SourceLine(_doc, "steps", str), [e], detailed_message=f"the `steps` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `id`, `inputs`, `outputs`, `requirements`, `hints`, `label`, `doc`, `cwlVersion`, `class`, `steps`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( id=id, inputs=inputs, outputs=outputs, requirements=requirements, hints=hints, label=label, doc=doc, cwlVersion=cwlVersion, steps=steps, extension_fields=extension_fields, loadingOptions=loadingOptions, ) loadingOptions.idx[cast(str, id)] = (_constructed, loadingOptions) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.id is not None: u = save_relative_uri(self.id, base_url, True, None, relative_uris) r["id"] = u if self.class_ is not None: uri = self.loadingOptions.vocab[self.class_] if p := self.loadingOptions.rvocab.get(uri[: -len(self.class_)]): uri = f"{p}:{self.class_}" else: uri = self.class_ u = save_relative_uri(uri, self.id, False, None, relative_uris) r["class"] = u if self.inputs is not None: r["inputs"] = save( self.inputs, top=False, base_url=self.id, relative_uris=relative_uris ) if self.outputs is not None: r["outputs"] = save( self.outputs, top=False, base_url=self.id, relative_uris=relative_uris ) if self.requirements is not None: r["requirements"] = save( self.requirements, top=False, base_url=self.id, relative_uris=relative_uris, ) if self.hints is not None: r["hints"] = save( self.hints, top=False, base_url=self.id, relative_uris=relative_uris ) if self.label is not None: r["label"] = save( self.label, top=False, base_url=self.id, relative_uris=relative_uris ) if self.doc is not None: r["doc"] = save( self.doc, top=False, base_url=self.id, relative_uris=relative_uris ) if self.cwlVersion is not None: u = save_relative_uri(self.cwlVersion, self.id, False, None, relative_uris) r["cwlVersion"] = u if self.steps is not None: r["steps"] = save( self.steps, top=False, base_url=self.id, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset( [ "id", "inputs", "outputs", "requirements", "hints", "label", "doc", "cwlVersion", "class", "steps", ] ) class SubworkflowFeatureRequirement(ProcessRequirement): """ Indicates that the workflow platform must support nested workflows in the `run` field of [WorkflowStep](#WorkflowStep). """ def __init__( self, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.class_ = "SubworkflowFeatureRequirement" def __eq__(self, other: Any) -> bool: if isinstance(other, SubworkflowFeatureRequirement): return bool(self.class_ == other.class_) return False def __hash__(self) -> int: return hash((self.class_)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "SubworkflowFeatureRequirement": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("class") is None: raise ValidationException("missing required field `class`", None, []) class_ = load_field( _doc.get("class"), uri_SubworkflowFeatureRequirement_classLoader_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("class") ) if class_ not in (cls.__name__, loadingOptions.vocab.get(cls.__name__)): raise ValidationException(f"tried `{cls.__name__}` but") except ValidationException as e: raise e extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `class`".format(k), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.class_ is not None: uri = self.loadingOptions.vocab[self.class_] if p := self.loadingOptions.rvocab.get(uri[: -len(self.class_)]): uri = f"{p}:{self.class_}" else: uri = self.class_ u = save_relative_uri(uri, base_url, False, None, relative_uris) r["class"] = u # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["class"]) class ScatterFeatureRequirement(ProcessRequirement): """ Indicates that the workflow platform must support the `scatter` and `scatterMethod` fields of [WorkflowStep](#WorkflowStep). """ def __init__( self, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.class_ = "ScatterFeatureRequirement" def __eq__(self, other: Any) -> bool: if isinstance(other, ScatterFeatureRequirement): return bool(self.class_ == other.class_) return False def __hash__(self) -> int: return hash((self.class_)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "ScatterFeatureRequirement": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("class") is None: raise ValidationException("missing required field `class`", None, []) class_ = load_field( _doc.get("class"), uri_ScatterFeatureRequirement_classLoader_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("class") ) if class_ not in (cls.__name__, loadingOptions.vocab.get(cls.__name__)): raise ValidationException(f"tried `{cls.__name__}` but") except ValidationException as e: raise e extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `class`".format(k), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.class_ is not None: uri = self.loadingOptions.vocab[self.class_] if p := self.loadingOptions.rvocab.get(uri[: -len(self.class_)]): uri = f"{p}:{self.class_}" else: uri = self.class_ u = save_relative_uri(uri, base_url, False, None, relative_uris) r["class"] = u # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["class"]) class MultipleInputFeatureRequirement(ProcessRequirement): """ Indicates that the workflow platform must support multiple inbound data links listed in the `source` field of [WorkflowStepInput](#WorkflowStepInput). """ def __init__( self, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.class_ = "MultipleInputFeatureRequirement" def __eq__(self, other: Any) -> bool: if isinstance(other, MultipleInputFeatureRequirement): return bool(self.class_ == other.class_) return False def __hash__(self) -> int: return hash((self.class_)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "MultipleInputFeatureRequirement": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("class") is None: raise ValidationException("missing required field `class`", None, []) class_ = load_field( _doc.get("class"), uri_MultipleInputFeatureRequirement_classLoader_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("class") ) if class_ not in (cls.__name__, loadingOptions.vocab.get(cls.__name__)): raise ValidationException(f"tried `{cls.__name__}` but") except ValidationException as e: raise e extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `class`".format(k), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.class_ is not None: uri = self.loadingOptions.vocab[self.class_] if p := self.loadingOptions.rvocab.get(uri[: -len(self.class_)]): uri = f"{p}:{self.class_}" else: uri = self.class_ u = save_relative_uri(uri, base_url, False, None, relative_uris) r["class"] = u # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["class"]) class StepInputExpressionRequirement(ProcessRequirement): """ Indicate that the workflow platform must support the `valueFrom` field of [WorkflowStepInput](#WorkflowStepInput). """ def __init__( self, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.class_ = "StepInputExpressionRequirement" def __eq__(self, other: Any) -> bool: if isinstance(other, StepInputExpressionRequirement): return bool(self.class_ == other.class_) return False def __hash__(self) -> int: return hash((self.class_)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "StepInputExpressionRequirement": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("class") is None: raise ValidationException("missing required field `class`", None, []) class_ = load_field( _doc.get("class"), uri_StepInputExpressionRequirement_classLoader_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("class") ) if class_ not in (cls.__name__, loadingOptions.vocab.get(cls.__name__)): raise ValidationException(f"tried `{cls.__name__}` but") except ValidationException as e: raise e extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `class`".format(k), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.class_ is not None: uri = self.loadingOptions.vocab[self.class_] if p := self.loadingOptions.rvocab.get(uri[: -len(self.class_)]): uri = f"{p}:{self.class_}" else: uri = self.class_ u = save_relative_uri(uri, base_url, False, None, relative_uris) r["class"] = u # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["class"]) class LoadListingRequirement(ProcessRequirement): def __init__( self, loadListing: Any, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.class_ = "LoadListingRequirement" self.loadListing = loadListing def __eq__(self, other: Any) -> bool: if isinstance(other, LoadListingRequirement): return bool( self.class_ == other.class_ and self.loadListing == other.loadListing ) return False def __hash__(self) -> int: return hash((self.class_, self.loadListing)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "LoadListingRequirement": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("class") is None: raise ValidationException("missing required field `class`", None, []) class_ = load_field( _doc.get("class"), uri_strtype_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("class") ) if class_ not in (cls.__name__, loadingOptions.vocab.get(cls.__name__)): raise ValidationException(f"tried `{cls.__name__}` but") except ValidationException as e: raise e try: if _doc.get("loadListing") is None: raise ValidationException("missing required field `loadListing`", None, []) loadListing = load_field( _doc.get("loadListing"), union_of_LoadListingEnumLoader, baseuri, loadingOptions, lc=_doc.get("loadListing") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `loadListing`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("loadListing") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `loadListing` field is not valid because:", SourceLine(_doc, "loadListing", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `loadListing` field is not valid because:", SourceLine(_doc, "loadListing", str), [e], detailed_message=f"the `loadListing` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `class`, `loadListing`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( loadListing=loadListing, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.class_ is not None: uri = self.loadingOptions.vocab[self.class_] if p := self.loadingOptions.rvocab.get(uri[: -len(self.class_)]): uri = f"{p}:{self.class_}" else: uri = self.class_ u = save_relative_uri(uri, base_url, False, None, relative_uris) r["class"] = u if self.loadListing is not None: r["loadListing"] = save( self.loadListing, top=False, base_url=base_url, relative_uris=relative_uris, ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["class", "loadListing"]) class InplaceUpdateRequirement(ProcessRequirement): def __init__( self, inplaceUpdate: Any, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.class_ = "InplaceUpdateRequirement" self.inplaceUpdate = inplaceUpdate def __eq__(self, other: Any) -> bool: if isinstance(other, InplaceUpdateRequirement): return bool( self.class_ == other.class_ and self.inplaceUpdate == other.inplaceUpdate ) return False def __hash__(self) -> int: return hash((self.class_, self.inplaceUpdate)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "InplaceUpdateRequirement": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("class") is None: raise ValidationException("missing required field `class`", None, []) class_ = load_field( _doc.get("class"), uri_strtype_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("class") ) if class_ not in (cls.__name__, loadingOptions.vocab.get(cls.__name__)): raise ValidationException(f"tried `{cls.__name__}` but") except ValidationException as e: raise e try: if _doc.get("inplaceUpdate") is None: raise ValidationException("missing required field `inplaceUpdate`", None, []) inplaceUpdate = load_field( _doc.get("inplaceUpdate"), booltype, baseuri, loadingOptions, lc=_doc.get("inplaceUpdate") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `inplaceUpdate`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("inplaceUpdate") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `inplaceUpdate` field is not valid because:", SourceLine(_doc, "inplaceUpdate", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `inplaceUpdate` field is not valid because:", SourceLine(_doc, "inplaceUpdate", str), [e], detailed_message=f"the `inplaceUpdate` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `class`, `inplaceUpdate`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( inplaceUpdate=inplaceUpdate, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.class_ is not None: uri = self.loadingOptions.vocab[self.class_] if p := self.loadingOptions.rvocab.get(uri[: -len(self.class_)]): uri = f"{p}:{self.class_}" else: uri = self.class_ u = save_relative_uri(uri, base_url, False, None, relative_uris) r["class"] = u if self.inplaceUpdate is not None: r["inplaceUpdate"] = save( self.inplaceUpdate, top=False, base_url=base_url, relative_uris=relative_uris, ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["class", "inplaceUpdate"]) class Secrets(ProcessRequirement): def __init__( self, secrets: Any, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.class_ = "Secrets" self.secrets = secrets def __eq__(self, other: Any) -> bool: if isinstance(other, Secrets): return bool(self.class_ == other.class_ and self.secrets == other.secrets) return False def __hash__(self) -> int: return hash((self.class_, self.secrets)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "Secrets": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("class") is None: raise ValidationException("missing required field `class`", None, []) class_ = load_field( _doc.get("class"), uri_strtype_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("class") ) if class_ not in (cls.__name__, loadingOptions.vocab.get(cls.__name__)): raise ValidationException(f"tried `{cls.__name__}` but") except ValidationException as e: raise e try: if _doc.get("secrets") is None: raise ValidationException("missing required field `secrets`", None, []) secrets = load_field( _doc.get("secrets"), uri_array_of_strtype_False_False_0_None, baseuri, loadingOptions, lc=_doc.get("secrets") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `secrets`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("secrets") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `secrets` field is not valid because:", SourceLine(_doc, "secrets", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `secrets` field is not valid because:", SourceLine(_doc, "secrets", str), [e], detailed_message=f"the `secrets` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `class`, `secrets`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( secrets=secrets, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.class_ is not None: uri = self.loadingOptions.vocab[self.class_] if p := self.loadingOptions.rvocab.get(uri[: -len(self.class_)]): uri = f"{p}:{self.class_}" else: uri = self.class_ u = save_relative_uri(uri, base_url, False, None, relative_uris) r["class"] = u if self.secrets is not None: u = save_relative_uri(self.secrets, base_url, False, 0, relative_uris) r["secrets"] = u # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["class", "secrets"]) class TimeLimit(ProcessRequirement): """ Set an upper limit on the execution time of a CommandLineTool or ExpressionTool. A tool execution which exceeds the time limit may be preemptively terminated and considered failed. May also be used by batch systems to make scheduling decisions. """ def __init__( self, timelimit: Any, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.class_ = "TimeLimit" self.timelimit = timelimit def __eq__(self, other: Any) -> bool: if isinstance(other, TimeLimit): return bool( self.class_ == other.class_ and self.timelimit == other.timelimit ) return False def __hash__(self) -> int: return hash((self.class_, self.timelimit)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "TimeLimit": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("class") is None: raise ValidationException("missing required field `class`", None, []) class_ = load_field( _doc.get("class"), uri_strtype_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("class") ) if class_ not in (cls.__name__, loadingOptions.vocab.get(cls.__name__)): raise ValidationException(f"tried `{cls.__name__}` but") except ValidationException as e: raise e try: if _doc.get("timelimit") is None: raise ValidationException("missing required field `timelimit`", None, []) timelimit = load_field( _doc.get("timelimit"), union_of_inttype_or_strtype, baseuri, loadingOptions, lc=_doc.get("timelimit") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `timelimit`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("timelimit") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `timelimit` field is not valid because:", SourceLine(_doc, "timelimit", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `timelimit` field is not valid because:", SourceLine(_doc, "timelimit", str), [e], detailed_message=f"the `timelimit` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `class`, `timelimit`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( timelimit=timelimit, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.class_ is not None: uri = self.loadingOptions.vocab[self.class_] if p := self.loadingOptions.rvocab.get(uri[: -len(self.class_)]): uri = f"{p}:{self.class_}" else: uri = self.class_ u = save_relative_uri(uri, base_url, False, None, relative_uris) r["class"] = u if self.timelimit is not None: r["timelimit"] = save( self.timelimit, top=False, base_url=base_url, relative_uris=relative_uris, ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["class", "timelimit"]) class WorkReuse(ProcessRequirement): """ For implementations that support reusing output from past work (on the assumption that same code and same input produce same results), control whether to enable or disable the reuse behavior for a particular tool or step (to accommodate situations where that assumption is incorrect). A reused step is not executed but instead returns the same output as the original execution. If `enableReuse` is not specified, correct tools should assume it is enabled by default. """ def __init__( self, enableReuse: Any, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.class_ = "WorkReuse" self.enableReuse = enableReuse def __eq__(self, other: Any) -> bool: if isinstance(other, WorkReuse): return bool( self.class_ == other.class_ and self.enableReuse == other.enableReuse ) return False def __hash__(self) -> int: return hash((self.class_, self.enableReuse)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "WorkReuse": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("class") is None: raise ValidationException("missing required field `class`", None, []) class_ = load_field( _doc.get("class"), uri_strtype_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("class") ) if class_ not in (cls.__name__, loadingOptions.vocab.get(cls.__name__)): raise ValidationException(f"tried `{cls.__name__}` but") except ValidationException as e: raise e try: if _doc.get("enableReuse") is None: raise ValidationException("missing required field `enableReuse`", None, []) enableReuse = load_field( _doc.get("enableReuse"), union_of_booltype_or_strtype, baseuri, loadingOptions, lc=_doc.get("enableReuse") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `enableReuse`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("enableReuse") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `enableReuse` field is not valid because:", SourceLine(_doc, "enableReuse", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `enableReuse` field is not valid because:", SourceLine(_doc, "enableReuse", str), [e], detailed_message=f"the `enableReuse` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `class`, `enableReuse`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( enableReuse=enableReuse, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.class_ is not None: uri = self.loadingOptions.vocab[self.class_] if p := self.loadingOptions.rvocab.get(uri[: -len(self.class_)]): uri = f"{p}:{self.class_}" else: uri = self.class_ u = save_relative_uri(uri, base_url, False, None, relative_uris) r["class"] = u if self.enableReuse is not None: r["enableReuse"] = save( self.enableReuse, top=False, base_url=base_url, relative_uris=relative_uris, ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["class", "enableReuse"]) class NetworkAccess(ProcessRequirement): """ Indicate whether a process requires outgoing IPv4/IPv6 network access. Choice of IPv4 or IPv6 is implementation and site specific, correct tools must support both. If `networkAccess` is false or not specified, tools must not assume network access, except for localhost (the loopback device). If `networkAccess` is true, the tool must be able to make outgoing connections to network resources. Resources may be on a private subnet or the public Internet. However, implementations and sites may apply their own security policies to restrict what is accessible by the tool. Enabling network access does not imply a publicly routable IP address or the ability to accept inbound connections. """ def __init__( self, networkAccess: Any, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.class_ = "NetworkAccess" self.networkAccess = networkAccess def __eq__(self, other: Any) -> bool: if isinstance(other, NetworkAccess): return bool( self.class_ == other.class_ and self.networkAccess == other.networkAccess ) return False def __hash__(self) -> int: return hash((self.class_, self.networkAccess)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "NetworkAccess": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("class") is None: raise ValidationException("missing required field `class`", None, []) class_ = load_field( _doc.get("class"), uri_strtype_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("class") ) if class_ not in (cls.__name__, loadingOptions.vocab.get(cls.__name__)): raise ValidationException(f"tried `{cls.__name__}` but") except ValidationException as e: raise e try: if _doc.get("networkAccess") is None: raise ValidationException("missing required field `networkAccess`", None, []) networkAccess = load_field( _doc.get("networkAccess"), union_of_booltype_or_strtype, baseuri, loadingOptions, lc=_doc.get("networkAccess") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `networkAccess`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("networkAccess") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `networkAccess` field is not valid because:", SourceLine(_doc, "networkAccess", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `networkAccess` field is not valid because:", SourceLine(_doc, "networkAccess", str), [e], detailed_message=f"the `networkAccess` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `class`, `networkAccess`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( networkAccess=networkAccess, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.class_ is not None: uri = self.loadingOptions.vocab[self.class_] if p := self.loadingOptions.rvocab.get(uri[: -len(self.class_)]): uri = f"{p}:{self.class_}" else: uri = self.class_ u = save_relative_uri(uri, base_url, False, None, relative_uris) r["class"] = u if self.networkAccess is not None: r["networkAccess"] = save( self.networkAccess, top=False, base_url=base_url, relative_uris=relative_uris, ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["class", "networkAccess"]) class ProcessGenerator(Process): id: str def __init__( self, inputs: Any, outputs: Any, run: Any, id: Optional[Any] = None, requirements: Optional[Any] = None, hints: Optional[Any] = None, label: Optional[Any] = None, doc: Optional[Any] = None, cwlVersion: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.id = id if id is not None else "_:" + str(_uuid__.uuid4()) self.inputs = inputs self.outputs = outputs self.requirements = requirements self.hints = hints self.label = label self.doc = doc self.cwlVersion = cwlVersion self.class_ = "ProcessGenerator" self.run = run def __eq__(self, other: Any) -> bool: if isinstance(other, ProcessGenerator): return bool( self.id == other.id and self.inputs == other.inputs and self.outputs == other.outputs and self.requirements == other.requirements and self.hints == other.hints and self.label == other.label and self.doc == other.doc and self.cwlVersion == other.cwlVersion and self.class_ == other.class_ and self.run == other.run ) return False def __hash__(self) -> int: return hash( ( self.id, self.inputs, self.outputs, self.requirements, self.hints, self.label, self.doc, self.cwlVersion, self.class_, self.run, ) ) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "ProcessGenerator": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] id = None if "id" in _doc: try: id = load_field( _doc.get("id"), uri_union_of_None_type_or_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("id") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `id`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("id") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `id` field is not valid because:", SourceLine(_doc, "id", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `id` field is not valid because:", SourceLine(_doc, "id", str), [e], detailed_message=f"the `id` field with value `{val}` " "is not valid because:", ) ) __original_id_is_none = id is None if id is None: if docRoot is not None: id = docRoot else: id = "_:" + str(_uuid__.uuid4()) if not __original_id_is_none: baseuri = cast(str, id) try: if _doc.get("class") is None: raise ValidationException("missing required field `class`", None, []) class_ = load_field( _doc.get("class"), uri_strtype_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("class") ) if class_ not in (cls.__name__, loadingOptions.vocab.get(cls.__name__)): raise ValidationException(f"tried `{cls.__name__}` but") except ValidationException as e: raise e try: if _doc.get("inputs") is None: raise ValidationException("missing required field `inputs`", None, []) inputs = load_field( _doc.get("inputs"), idmap_inputs_array_of_InputParameterLoader, baseuri, loadingOptions, lc=_doc.get("inputs") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `inputs`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("inputs") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `inputs` field is not valid because:", SourceLine(_doc, "inputs", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `inputs` field is not valid because:", SourceLine(_doc, "inputs", str), [e], detailed_message=f"the `inputs` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("outputs") is None: raise ValidationException("missing required field `outputs`", None, []) outputs = load_field( _doc.get("outputs"), idmap_outputs_array_of_OutputParameterLoader, baseuri, loadingOptions, lc=_doc.get("outputs") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `outputs`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("outputs") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `outputs` field is not valid because:", SourceLine(_doc, "outputs", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `outputs` field is not valid because:", SourceLine(_doc, "outputs", str), [e], detailed_message=f"the `outputs` field with value `{val}` " "is not valid because:", ) ) requirements = None if "requirements" in _doc: try: requirements = load_field( _doc.get("requirements"), idmap_requirements_union_of_None_type_or_array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader_or_LoadListingRequirementLoader_or_InplaceUpdateRequirementLoader_or_SecretsLoader_or_TimeLimitLoader_or_WorkReuseLoader_or_NetworkAccessLoader_or_MPIRequirementLoader_or_CUDARequirementLoader_or_ShmSizeLoader, baseuri, loadingOptions, lc=_doc.get("requirements") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `requirements`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("requirements") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `requirements` field is not valid because:", SourceLine(_doc, "requirements", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `requirements` field is not valid because:", SourceLine(_doc, "requirements", str), [e], detailed_message=f"the `requirements` field with value `{val}` " "is not valid because:", ) ) hints = None if "hints" in _doc: try: hints = load_field( _doc.get("hints"), idmap_hints_union_of_None_type_or_array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader_or_LoadListingRequirementLoader_or_InplaceUpdateRequirementLoader_or_SecretsLoader_or_TimeLimitLoader_or_WorkReuseLoader_or_NetworkAccessLoader_or_MPIRequirementLoader_or_CUDARequirementLoader_or_ShmSizeLoader_or_Any_type, baseuri, loadingOptions, lc=_doc.get("hints") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `hints`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("hints") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `hints` field is not valid because:", SourceLine(_doc, "hints", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `hints` field is not valid because:", SourceLine(_doc, "hints", str), [e], detailed_message=f"the `hints` field with value `{val}` " "is not valid because:", ) ) label = None if "label" in _doc: try: label = load_field( _doc.get("label"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("label") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `label`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("label") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [e], detailed_message=f"the `label` field with value `{val}` " "is not valid because:", ) ) doc = None if "doc" in _doc: try: doc = load_field( _doc.get("doc"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("doc") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `doc`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("doc") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [e], detailed_message=f"the `doc` field with value `{val}` " "is not valid because:", ) ) cwlVersion = None if "cwlVersion" in _doc: try: cwlVersion = load_field( _doc.get("cwlVersion"), uri_union_of_None_type_or_CWLVersionLoader_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("cwlVersion") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `cwlVersion`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("cwlVersion") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `cwlVersion` field is not valid because:", SourceLine(_doc, "cwlVersion", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `cwlVersion` field is not valid because:", SourceLine(_doc, "cwlVersion", str), [e], detailed_message=f"the `cwlVersion` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("run") is None: raise ValidationException("missing required field `run`", None, []) run = load_field( _doc.get("run"), uri_union_of_strtype_or_CommandLineToolLoader_or_ExpressionToolLoader_or_WorkflowLoader_or_ProcessGeneratorLoader_False_False_None_None, baseuri, loadingOptions, lc=_doc.get("run") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `run`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("run") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `run` field is not valid because:", SourceLine(_doc, "run", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `run` field is not valid because:", SourceLine(_doc, "run", str), [e], detailed_message=f"the `run` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `id`, `inputs`, `outputs`, `requirements`, `hints`, `label`, `doc`, `cwlVersion`, `class`, `run`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( id=id, inputs=inputs, outputs=outputs, requirements=requirements, hints=hints, label=label, doc=doc, cwlVersion=cwlVersion, run=run, extension_fields=extension_fields, loadingOptions=loadingOptions, ) loadingOptions.idx[cast(str, id)] = (_constructed, loadingOptions) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.id is not None: u = save_relative_uri(self.id, base_url, True, None, relative_uris) r["id"] = u if self.class_ is not None: uri = self.loadingOptions.vocab[self.class_] if p := self.loadingOptions.rvocab.get(uri[: -len(self.class_)]): uri = f"{p}:{self.class_}" else: uri = self.class_ u = save_relative_uri(uri, self.id, False, None, relative_uris) r["class"] = u if self.inputs is not None: r["inputs"] = save( self.inputs, top=False, base_url=self.id, relative_uris=relative_uris ) if self.outputs is not None: r["outputs"] = save( self.outputs, top=False, base_url=self.id, relative_uris=relative_uris ) if self.requirements is not None: r["requirements"] = save( self.requirements, top=False, base_url=self.id, relative_uris=relative_uris, ) if self.hints is not None: r["hints"] = save( self.hints, top=False, base_url=self.id, relative_uris=relative_uris ) if self.label is not None: r["label"] = save( self.label, top=False, base_url=self.id, relative_uris=relative_uris ) if self.doc is not None: r["doc"] = save( self.doc, top=False, base_url=self.id, relative_uris=relative_uris ) if self.cwlVersion is not None: u = save_relative_uri(self.cwlVersion, self.id, False, None, relative_uris) r["cwlVersion"] = u if self.run is not None: u = save_relative_uri(self.run, self.id, False, None, relative_uris) r["run"] = u # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset( [ "id", "inputs", "outputs", "requirements", "hints", "label", "doc", "cwlVersion", "class", "run", ] ) class MPIRequirement(ProcessRequirement): """ Indicates that a process requires an MPI runtime. """ def __init__( self, processes: Any, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.class_ = "MPIRequirement" self.processes = processes def __eq__(self, other: Any) -> bool: if isinstance(other, MPIRequirement): return bool( self.class_ == other.class_ and self.processes == other.processes ) return False def __hash__(self) -> int: return hash((self.class_, self.processes)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "MPIRequirement": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("class") is None: raise ValidationException("missing required field `class`", None, []) class_ = load_field( _doc.get("class"), uri_strtype_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("class") ) if class_ not in (cls.__name__, loadingOptions.vocab.get(cls.__name__)): raise ValidationException(f"tried `{cls.__name__}` but") except ValidationException as e: raise e try: if _doc.get("processes") is None: raise ValidationException("missing required field `processes`", None, []) processes = load_field( _doc.get("processes"), union_of_inttype_or_ExpressionLoader, baseuri, loadingOptions, lc=_doc.get("processes") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `processes`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("processes") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `processes` field is not valid because:", SourceLine(_doc, "processes", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `processes` field is not valid because:", SourceLine(_doc, "processes", str), [e], detailed_message=f"the `processes` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `class`, `processes`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( processes=processes, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.class_ is not None: uri = self.loadingOptions.vocab[self.class_] if p := self.loadingOptions.rvocab.get(uri[: -len(self.class_)]): uri = f"{p}:{self.class_}" else: uri = self.class_ u = save_relative_uri(uri, base_url, False, None, relative_uris) r["class"] = u if self.processes is not None: r["processes"] = save( self.processes, top=False, base_url=base_url, relative_uris=relative_uris, ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["class", "processes"]) class CUDARequirement(ProcessRequirement): """ Require support for NVIDA CUDA (GPU hardware acceleration). """ def __init__( self, cudaComputeCapability: Any, cudaVersionMin: Any, cudaDeviceCountMax: Optional[Any] = None, cudaDeviceCountMin: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.class_ = "CUDARequirement" self.cudaComputeCapability = cudaComputeCapability self.cudaDeviceCountMax = cudaDeviceCountMax self.cudaDeviceCountMin = cudaDeviceCountMin self.cudaVersionMin = cudaVersionMin def __eq__(self, other: Any) -> bool: if isinstance(other, CUDARequirement): return bool( self.class_ == other.class_ and self.cudaComputeCapability == other.cudaComputeCapability and self.cudaDeviceCountMax == other.cudaDeviceCountMax and self.cudaDeviceCountMin == other.cudaDeviceCountMin and self.cudaVersionMin == other.cudaVersionMin ) return False def __hash__(self) -> int: return hash( ( self.class_, self.cudaComputeCapability, self.cudaDeviceCountMax, self.cudaDeviceCountMin, self.cudaVersionMin, ) ) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "CUDARequirement": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("class") is None: raise ValidationException("missing required field `class`", None, []) class_ = load_field( _doc.get("class"), uri_strtype_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("class") ) if class_ not in (cls.__name__, loadingOptions.vocab.get(cls.__name__)): raise ValidationException(f"tried `{cls.__name__}` but") except ValidationException as e: raise e try: if _doc.get("cudaComputeCapability") is None: raise ValidationException("missing required field `cudaComputeCapability`", None, []) cudaComputeCapability = load_field( _doc.get("cudaComputeCapability"), union_of_strtype_or_array_of_strtype, baseuri, loadingOptions, lc=_doc.get("cudaComputeCapability") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `cudaComputeCapability`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("cudaComputeCapability") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `cudaComputeCapability` field is not valid because:", SourceLine(_doc, "cudaComputeCapability", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `cudaComputeCapability` field is not valid because:", SourceLine(_doc, "cudaComputeCapability", str), [e], detailed_message=f"the `cudaComputeCapability` field with value `{val}` " "is not valid because:", ) ) cudaDeviceCountMax = None if "cudaDeviceCountMax" in _doc: try: cudaDeviceCountMax = load_field( _doc.get("cudaDeviceCountMax"), union_of_None_type_or_inttype_or_ExpressionLoader, baseuri, loadingOptions, lc=_doc.get("cudaDeviceCountMax") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `cudaDeviceCountMax`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("cudaDeviceCountMax") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `cudaDeviceCountMax` field is not valid because:", SourceLine(_doc, "cudaDeviceCountMax", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `cudaDeviceCountMax` field is not valid because:", SourceLine(_doc, "cudaDeviceCountMax", str), [e], detailed_message=f"the `cudaDeviceCountMax` field with value `{val}` " "is not valid because:", ) ) cudaDeviceCountMin = None if "cudaDeviceCountMin" in _doc: try: cudaDeviceCountMin = load_field( _doc.get("cudaDeviceCountMin"), union_of_None_type_or_inttype_or_ExpressionLoader, baseuri, loadingOptions, lc=_doc.get("cudaDeviceCountMin") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `cudaDeviceCountMin`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("cudaDeviceCountMin") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `cudaDeviceCountMin` field is not valid because:", SourceLine(_doc, "cudaDeviceCountMin", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `cudaDeviceCountMin` field is not valid because:", SourceLine(_doc, "cudaDeviceCountMin", str), [e], detailed_message=f"the `cudaDeviceCountMin` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("cudaVersionMin") is None: raise ValidationException("missing required field `cudaVersionMin`", None, []) cudaVersionMin = load_field( _doc.get("cudaVersionMin"), strtype, baseuri, loadingOptions, lc=_doc.get("cudaVersionMin") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `cudaVersionMin`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("cudaVersionMin") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `cudaVersionMin` field is not valid because:", SourceLine(_doc, "cudaVersionMin", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `cudaVersionMin` field is not valid because:", SourceLine(_doc, "cudaVersionMin", str), [e], detailed_message=f"the `cudaVersionMin` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `class`, `cudaComputeCapability`, `cudaDeviceCountMax`, `cudaDeviceCountMin`, `cudaVersionMin`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( cudaComputeCapability=cudaComputeCapability, cudaDeviceCountMax=cudaDeviceCountMax, cudaDeviceCountMin=cudaDeviceCountMin, cudaVersionMin=cudaVersionMin, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.class_ is not None: uri = self.loadingOptions.vocab[self.class_] if p := self.loadingOptions.rvocab.get(uri[: -len(self.class_)]): uri = f"{p}:{self.class_}" else: uri = self.class_ u = save_relative_uri(uri, base_url, False, None, relative_uris) r["class"] = u if self.cudaComputeCapability is not None: r["cudaComputeCapability"] = save( self.cudaComputeCapability, top=False, base_url=base_url, relative_uris=relative_uris, ) if self.cudaDeviceCountMax is not None: r["cudaDeviceCountMax"] = save( self.cudaDeviceCountMax, top=False, base_url=base_url, relative_uris=relative_uris, ) if self.cudaDeviceCountMin is not None: r["cudaDeviceCountMin"] = save( self.cudaDeviceCountMin, top=False, base_url=base_url, relative_uris=relative_uris, ) if self.cudaVersionMin is not None: r["cudaVersionMin"] = save( self.cudaVersionMin, top=False, base_url=base_url, relative_uris=relative_uris, ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset( [ "class", "cudaComputeCapability", "cudaDeviceCountMax", "cudaDeviceCountMin", "cudaVersionMin", ] ) class ShmSize(ProcessRequirement): def __init__( self, shmSize: Any, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.class_ = "ShmSize" self.shmSize = shmSize def __eq__(self, other: Any) -> bool: if isinstance(other, ShmSize): return bool(self.class_ == other.class_ and self.shmSize == other.shmSize) return False def __hash__(self) -> int: return hash((self.class_, self.shmSize)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "ShmSize": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("class") is None: raise ValidationException("missing required field `class`", None, []) class_ = load_field( _doc.get("class"), uri_strtype_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("class") ) if class_ not in (cls.__name__, loadingOptions.vocab.get(cls.__name__)): raise ValidationException(f"tried `{cls.__name__}` but") except ValidationException as e: raise e try: if _doc.get("shmSize") is None: raise ValidationException("missing required field `shmSize`", None, []) shmSize = load_field( _doc.get("shmSize"), strtype, baseuri, loadingOptions, lc=_doc.get("shmSize") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `shmSize`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("shmSize") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `shmSize` field is not valid because:", SourceLine(_doc, "shmSize", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `shmSize` field is not valid because:", SourceLine(_doc, "shmSize", str), [e], detailed_message=f"the `shmSize` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `class`, `shmSize`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( shmSize=shmSize, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.class_ is not None: uri = self.loadingOptions.vocab[self.class_] if p := self.loadingOptions.rvocab.get(uri[: -len(self.class_)]): uri = f"{p}:{self.class_}" else: uri = self.class_ u = save_relative_uri(uri, base_url, False, None, relative_uris) r["class"] = u if self.shmSize is not None: r["shmSize"] = save( self.shmSize, top=False, base_url=base_url, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["class", "shmSize"]) _vocab = { "Any": "https://w3id.org/cwl/salad#Any", "ArraySchema": "https://w3id.org/cwl/salad#ArraySchema", "CUDARequirement": "http://commonwl.org/cwltool#CUDARequirement", "CWLArraySchema": "https://w3id.org/cwl/cwl#CWLArraySchema", "CWLInputFile": "https://w3id.org/cwl/cwl#CWLInputFile", "CWLObjectType": "https://w3id.org/cwl/cwl#CWLObjectType", "CWLRecordField": "https://w3id.org/cwl/cwl#CWLRecordField", "CWLRecordSchema": "https://w3id.org/cwl/cwl#CWLRecordSchema", "CWLType": "https://w3id.org/cwl/cwl#CWLType", "CWLVersion": "https://w3id.org/cwl/cwl#CWLVersion", "CommandInputArraySchema": "https://w3id.org/cwl/cwl#CommandInputArraySchema", "CommandInputEnumSchema": "https://w3id.org/cwl/cwl#CommandInputEnumSchema", "CommandInputParameter": "https://w3id.org/cwl/cwl#CommandInputParameter", "CommandInputRecordField": "https://w3id.org/cwl/cwl#CommandInputRecordField", "CommandInputRecordSchema": "https://w3id.org/cwl/cwl#CommandInputRecordSchema", "CommandLineBinding": "https://w3id.org/cwl/cwl#CommandLineBinding", "CommandLineTool": "https://w3id.org/cwl/cwl#CommandLineTool", "CommandOutputArraySchema": "https://w3id.org/cwl/cwl#CommandOutputArraySchema", "CommandOutputBinding": "https://w3id.org/cwl/cwl#CommandOutputBinding", "CommandOutputEnumSchema": "https://w3id.org/cwl/cwl#CommandOutputEnumSchema", "CommandOutputParameter": "https://w3id.org/cwl/cwl#CommandOutputParameter", "CommandOutputRecordField": "https://w3id.org/cwl/cwl#CommandOutputRecordField", "CommandOutputRecordSchema": "https://w3id.org/cwl/cwl#CommandOutputRecordSchema", "Directory": "https://w3id.org/cwl/cwl#Directory", "Dirent": "https://w3id.org/cwl/cwl#Dirent", "DockerRequirement": "https://w3id.org/cwl/cwl#DockerRequirement", "Documented": "https://w3id.org/cwl/salad#Documented", "EnumSchema": "https://w3id.org/cwl/salad#EnumSchema", "EnvVarRequirement": "https://w3id.org/cwl/cwl#EnvVarRequirement", "EnvironmentDef": "https://w3id.org/cwl/cwl#EnvironmentDef", "Expression": "https://w3id.org/cwl/cwl#Expression", "ExpressionPlaceholder": "https://w3id.org/cwl/cwl#ExpressionPlaceholder", "ExpressionTool": "https://w3id.org/cwl/cwl#ExpressionTool", "ExpressionToolOutputParameter": "https://w3id.org/cwl/cwl#ExpressionToolOutputParameter", "File": "https://w3id.org/cwl/cwl#File", "InitialWorkDirRequirement": "https://w3id.org/cwl/cwl#InitialWorkDirRequirement", "InlineJavascriptRequirement": "https://w3id.org/cwl/cwl#InlineJavascriptRequirement", "InplaceUpdateRequirement": "http://commonwl.org/cwltool#InplaceUpdateRequirement", "InputArraySchema": "https://w3id.org/cwl/cwl#InputArraySchema", "InputBinding": "https://w3id.org/cwl/cwl#InputBinding", "InputEnumSchema": "https://w3id.org/cwl/cwl#InputEnumSchema", "InputParameter": "https://w3id.org/cwl/cwl#InputParameter", "InputRecordField": "https://w3id.org/cwl/cwl#InputRecordField", "InputRecordSchema": "https://w3id.org/cwl/cwl#InputRecordSchema", "InputSchema": "https://w3id.org/cwl/cwl#InputSchema", "LinkMergeMethod": "https://w3id.org/cwl/cwl#LinkMergeMethod", "LoadListingRequirement": "http://commonwl.org/cwltool#LoadListingRequirement", "MPIRequirement": "http://commonwl.org/cwltool#MPIRequirement", "MapSchema": "https://w3id.org/cwl/salad#MapSchema", "MultipleInputFeatureRequirement": "https://w3id.org/cwl/cwl#MultipleInputFeatureRequirement", "NetworkAccess": "http://commonwl.org/cwltool#NetworkAccess", "OutputArraySchema": "https://w3id.org/cwl/cwl#OutputArraySchema", "OutputBinding": "https://w3id.org/cwl/cwl#OutputBinding", "OutputEnumSchema": "https://w3id.org/cwl/cwl#OutputEnumSchema", "OutputParameter": "https://w3id.org/cwl/cwl#OutputParameter", "OutputRecordField": "https://w3id.org/cwl/cwl#OutputRecordField", "OutputRecordSchema": "https://w3id.org/cwl/cwl#OutputRecordSchema", "OutputSchema": "https://w3id.org/cwl/cwl#OutputSchema", "Parameter": "https://w3id.org/cwl/cwl#Parameter", "PrimitiveType": "https://w3id.org/cwl/salad#PrimitiveType", "Process": "https://w3id.org/cwl/cwl#Process", "ProcessGenerator": "http://commonwl.org/cwltool#ProcessGenerator", "ProcessRequirement": "https://w3id.org/cwl/cwl#ProcessRequirement", "RecordField": "https://w3id.org/cwl/salad#RecordField", "RecordSchema": "https://w3id.org/cwl/salad#RecordSchema", "ResourceRequirement": "https://w3id.org/cwl/cwl#ResourceRequirement", "ScatterFeatureRequirement": "https://w3id.org/cwl/cwl#ScatterFeatureRequirement", "ScatterMethod": "https://w3id.org/cwl/cwl#ScatterMethod", "SchemaBase": "https://w3id.org/cwl/cwl#SchemaBase", "SchemaDefRequirement": "https://w3id.org/cwl/cwl#SchemaDefRequirement", "Secrets": "http://commonwl.org/cwltool#Secrets", "ShellCommandRequirement": "https://w3id.org/cwl/cwl#ShellCommandRequirement", "ShmSize": "http://commonwl.org/cwltool#ShmSize", "Sink": "https://w3id.org/cwl/cwl#Sink", "SoftwarePackage": "https://w3id.org/cwl/cwl#SoftwarePackage", "SoftwareRequirement": "https://w3id.org/cwl/cwl#SoftwareRequirement", "StepInputExpressionRequirement": "https://w3id.org/cwl/cwl#StepInputExpressionRequirement", "SubworkflowFeatureRequirement": "https://w3id.org/cwl/cwl#SubworkflowFeatureRequirement", "TimeLimit": "http://commonwl.org/cwltool#TimeLimit", "UnionSchema": "https://w3id.org/cwl/salad#UnionSchema", "WorkReuse": "http://commonwl.org/cwltool#WorkReuse", "Workflow": "https://w3id.org/cwl/cwl#Workflow", "WorkflowOutputParameter": "https://w3id.org/cwl/cwl#WorkflowOutputParameter", "WorkflowStep": "https://w3id.org/cwl/cwl#WorkflowStep", "WorkflowStepInput": "https://w3id.org/cwl/cwl#WorkflowStepInput", "WorkflowStepOutput": "https://w3id.org/cwl/cwl#WorkflowStepOutput", "array": "https://w3id.org/cwl/salad#array", "boolean": "http://www.w3.org/2001/XMLSchema#boolean", "deep_listing": "http://commonwl.org/cwltool#LoadListingRequirement/loadListing/LoadListingEnum/deep_listing", "dotproduct": "https://w3id.org/cwl/cwl#ScatterMethod/dotproduct", "double": "http://www.w3.org/2001/XMLSchema#double", "draft-2": "https://w3id.org/cwl/cwl#draft-2", "draft-3": "https://w3id.org/cwl/cwl#draft-3", "draft-3.dev1": "https://w3id.org/cwl/cwl#draft-3.dev1", "draft-3.dev2": "https://w3id.org/cwl/cwl#draft-3.dev2", "draft-3.dev3": "https://w3id.org/cwl/cwl#draft-3.dev3", "draft-3.dev4": "https://w3id.org/cwl/cwl#draft-3.dev4", "draft-3.dev5": "https://w3id.org/cwl/cwl#draft-3.dev5", "draft-4.dev1": "https://w3id.org/cwl/cwl#draft-4.dev1", "draft-4.dev2": "https://w3id.org/cwl/cwl#draft-4.dev2", "draft-4.dev3": "https://w3id.org/cwl/cwl#draft-4.dev3", "enum": "https://w3id.org/cwl/salad#enum", "flat_crossproduct": "https://w3id.org/cwl/cwl#ScatterMethod/flat_crossproduct", "float": "http://www.w3.org/2001/XMLSchema#float", "int": "http://www.w3.org/2001/XMLSchema#int", "long": "http://www.w3.org/2001/XMLSchema#long", "map": "https://w3id.org/cwl/salad#map", "merge_flattened": "https://w3id.org/cwl/cwl#LinkMergeMethod/merge_flattened", "merge_nested": "https://w3id.org/cwl/cwl#LinkMergeMethod/merge_nested", "nested_crossproduct": "https://w3id.org/cwl/cwl#ScatterMethod/nested_crossproduct", "no_listing": "http://commonwl.org/cwltool#LoadListingRequirement/loadListing/LoadListingEnum/no_listing", "null": "https://w3id.org/cwl/salad#null", "record": "https://w3id.org/cwl/salad#record", "shallow_listing": "http://commonwl.org/cwltool#LoadListingRequirement/loadListing/LoadListingEnum/shallow_listing", "stderr": "https://w3id.org/cwl/cwl#stderr", "stdout": "https://w3id.org/cwl/cwl#stdout", "string": "http://www.w3.org/2001/XMLSchema#string", "union": "https://w3id.org/cwl/salad#union", "v1.0": "https://w3id.org/cwl/cwl#v1.0", "v1.0.dev4": "https://w3id.org/cwl/cwl#v1.0.dev4", } _rvocab = { "https://w3id.org/cwl/salad#Any": "Any", "https://w3id.org/cwl/salad#ArraySchema": "ArraySchema", "http://commonwl.org/cwltool#CUDARequirement": "CUDARequirement", "https://w3id.org/cwl/cwl#CWLArraySchema": "CWLArraySchema", "https://w3id.org/cwl/cwl#CWLInputFile": "CWLInputFile", "https://w3id.org/cwl/cwl#CWLObjectType": "CWLObjectType", "https://w3id.org/cwl/cwl#CWLRecordField": "CWLRecordField", "https://w3id.org/cwl/cwl#CWLRecordSchema": "CWLRecordSchema", "https://w3id.org/cwl/cwl#CWLType": "CWLType", "https://w3id.org/cwl/cwl#CWLVersion": "CWLVersion", "https://w3id.org/cwl/cwl#CommandInputArraySchema": "CommandInputArraySchema", "https://w3id.org/cwl/cwl#CommandInputEnumSchema": "CommandInputEnumSchema", "https://w3id.org/cwl/cwl#CommandInputParameter": "CommandInputParameter", "https://w3id.org/cwl/cwl#CommandInputRecordField": "CommandInputRecordField", "https://w3id.org/cwl/cwl#CommandInputRecordSchema": "CommandInputRecordSchema", "https://w3id.org/cwl/cwl#CommandLineBinding": "CommandLineBinding", "https://w3id.org/cwl/cwl#CommandLineTool": "CommandLineTool", "https://w3id.org/cwl/cwl#CommandOutputArraySchema": "CommandOutputArraySchema", "https://w3id.org/cwl/cwl#CommandOutputBinding": "CommandOutputBinding", "https://w3id.org/cwl/cwl#CommandOutputEnumSchema": "CommandOutputEnumSchema", "https://w3id.org/cwl/cwl#CommandOutputParameter": "CommandOutputParameter", "https://w3id.org/cwl/cwl#CommandOutputRecordField": "CommandOutputRecordField", "https://w3id.org/cwl/cwl#CommandOutputRecordSchema": "CommandOutputRecordSchema", "https://w3id.org/cwl/cwl#Directory": "Directory", "https://w3id.org/cwl/cwl#Dirent": "Dirent", "https://w3id.org/cwl/cwl#DockerRequirement": "DockerRequirement", "https://w3id.org/cwl/salad#Documented": "Documented", "https://w3id.org/cwl/salad#EnumSchema": "EnumSchema", "https://w3id.org/cwl/cwl#EnvVarRequirement": "EnvVarRequirement", "https://w3id.org/cwl/cwl#EnvironmentDef": "EnvironmentDef", "https://w3id.org/cwl/cwl#Expression": "Expression", "https://w3id.org/cwl/cwl#ExpressionPlaceholder": "ExpressionPlaceholder", "https://w3id.org/cwl/cwl#ExpressionTool": "ExpressionTool", "https://w3id.org/cwl/cwl#ExpressionToolOutputParameter": "ExpressionToolOutputParameter", "https://w3id.org/cwl/cwl#File": "File", "https://w3id.org/cwl/cwl#InitialWorkDirRequirement": "InitialWorkDirRequirement", "https://w3id.org/cwl/cwl#InlineJavascriptRequirement": "InlineJavascriptRequirement", "http://commonwl.org/cwltool#InplaceUpdateRequirement": "InplaceUpdateRequirement", "https://w3id.org/cwl/cwl#InputArraySchema": "InputArraySchema", "https://w3id.org/cwl/cwl#InputBinding": "InputBinding", "https://w3id.org/cwl/cwl#InputEnumSchema": "InputEnumSchema", "https://w3id.org/cwl/cwl#InputParameter": "InputParameter", "https://w3id.org/cwl/cwl#InputRecordField": "InputRecordField", "https://w3id.org/cwl/cwl#InputRecordSchema": "InputRecordSchema", "https://w3id.org/cwl/cwl#InputSchema": "InputSchema", "https://w3id.org/cwl/cwl#LinkMergeMethod": "LinkMergeMethod", "http://commonwl.org/cwltool#LoadListingRequirement": "LoadListingRequirement", "http://commonwl.org/cwltool#MPIRequirement": "MPIRequirement", "https://w3id.org/cwl/salad#MapSchema": "MapSchema", "https://w3id.org/cwl/cwl#MultipleInputFeatureRequirement": "MultipleInputFeatureRequirement", "http://commonwl.org/cwltool#NetworkAccess": "NetworkAccess", "https://w3id.org/cwl/cwl#OutputArraySchema": "OutputArraySchema", "https://w3id.org/cwl/cwl#OutputBinding": "OutputBinding", "https://w3id.org/cwl/cwl#OutputEnumSchema": "OutputEnumSchema", "https://w3id.org/cwl/cwl#OutputParameter": "OutputParameter", "https://w3id.org/cwl/cwl#OutputRecordField": "OutputRecordField", "https://w3id.org/cwl/cwl#OutputRecordSchema": "OutputRecordSchema", "https://w3id.org/cwl/cwl#OutputSchema": "OutputSchema", "https://w3id.org/cwl/cwl#Parameter": "Parameter", "https://w3id.org/cwl/salad#PrimitiveType": "PrimitiveType", "https://w3id.org/cwl/cwl#Process": "Process", "http://commonwl.org/cwltool#ProcessGenerator": "ProcessGenerator", "https://w3id.org/cwl/cwl#ProcessRequirement": "ProcessRequirement", "https://w3id.org/cwl/salad#RecordField": "RecordField", "https://w3id.org/cwl/salad#RecordSchema": "RecordSchema", "https://w3id.org/cwl/cwl#ResourceRequirement": "ResourceRequirement", "https://w3id.org/cwl/cwl#ScatterFeatureRequirement": "ScatterFeatureRequirement", "https://w3id.org/cwl/cwl#ScatterMethod": "ScatterMethod", "https://w3id.org/cwl/cwl#SchemaBase": "SchemaBase", "https://w3id.org/cwl/cwl#SchemaDefRequirement": "SchemaDefRequirement", "http://commonwl.org/cwltool#Secrets": "Secrets", "https://w3id.org/cwl/cwl#ShellCommandRequirement": "ShellCommandRequirement", "http://commonwl.org/cwltool#ShmSize": "ShmSize", "https://w3id.org/cwl/cwl#Sink": "Sink", "https://w3id.org/cwl/cwl#SoftwarePackage": "SoftwarePackage", "https://w3id.org/cwl/cwl#SoftwareRequirement": "SoftwareRequirement", "https://w3id.org/cwl/cwl#StepInputExpressionRequirement": "StepInputExpressionRequirement", "https://w3id.org/cwl/cwl#SubworkflowFeatureRequirement": "SubworkflowFeatureRequirement", "http://commonwl.org/cwltool#TimeLimit": "TimeLimit", "https://w3id.org/cwl/salad#UnionSchema": "UnionSchema", "http://commonwl.org/cwltool#WorkReuse": "WorkReuse", "https://w3id.org/cwl/cwl#Workflow": "Workflow", "https://w3id.org/cwl/cwl#WorkflowOutputParameter": "WorkflowOutputParameter", "https://w3id.org/cwl/cwl#WorkflowStep": "WorkflowStep", "https://w3id.org/cwl/cwl#WorkflowStepInput": "WorkflowStepInput", "https://w3id.org/cwl/cwl#WorkflowStepOutput": "WorkflowStepOutput", "https://w3id.org/cwl/salad#array": "array", "http://www.w3.org/2001/XMLSchema#boolean": "boolean", "http://commonwl.org/cwltool#LoadListingRequirement/loadListing/LoadListingEnum/deep_listing": "deep_listing", "https://w3id.org/cwl/cwl#ScatterMethod/dotproduct": "dotproduct", "http://www.w3.org/2001/XMLSchema#double": "double", "https://w3id.org/cwl/cwl#draft-2": "draft-2", "https://w3id.org/cwl/cwl#draft-3": "draft-3", "https://w3id.org/cwl/cwl#draft-3.dev1": "draft-3.dev1", "https://w3id.org/cwl/cwl#draft-3.dev2": "draft-3.dev2", "https://w3id.org/cwl/cwl#draft-3.dev3": "draft-3.dev3", "https://w3id.org/cwl/cwl#draft-3.dev4": "draft-3.dev4", "https://w3id.org/cwl/cwl#draft-3.dev5": "draft-3.dev5", "https://w3id.org/cwl/cwl#draft-4.dev1": "draft-4.dev1", "https://w3id.org/cwl/cwl#draft-4.dev2": "draft-4.dev2", "https://w3id.org/cwl/cwl#draft-4.dev3": "draft-4.dev3", "https://w3id.org/cwl/salad#enum": "enum", "https://w3id.org/cwl/cwl#ScatterMethod/flat_crossproduct": "flat_crossproduct", "http://www.w3.org/2001/XMLSchema#float": "float", "http://www.w3.org/2001/XMLSchema#int": "int", "http://www.w3.org/2001/XMLSchema#long": "long", "https://w3id.org/cwl/salad#map": "map", "https://w3id.org/cwl/cwl#LinkMergeMethod/merge_flattened": "merge_flattened", "https://w3id.org/cwl/cwl#LinkMergeMethod/merge_nested": "merge_nested", "https://w3id.org/cwl/cwl#ScatterMethod/nested_crossproduct": "nested_crossproduct", "http://commonwl.org/cwltool#LoadListingRequirement/loadListing/LoadListingEnum/no_listing": "no_listing", "https://w3id.org/cwl/salad#null": "null", "https://w3id.org/cwl/salad#record": "record", "http://commonwl.org/cwltool#LoadListingRequirement/loadListing/LoadListingEnum/shallow_listing": "shallow_listing", "https://w3id.org/cwl/cwl#stderr": "stderr", "https://w3id.org/cwl/cwl#stdout": "stdout", "http://www.w3.org/2001/XMLSchema#string": "string", "https://w3id.org/cwl/salad#union": "union", "https://w3id.org/cwl/cwl#v1.0": "v1.0", "https://w3id.org/cwl/cwl#v1.0.dev4": "v1.0.dev4", } strtype = _PrimitiveLoader(str) inttype = _PrimitiveLoader(int) floattype = _PrimitiveLoader(float) booltype = _PrimitiveLoader(bool) None_type = _PrimitiveLoader(type(None)) Any_type = _AnyLoader() PrimitiveTypeLoader = _EnumLoader( ( "null", "boolean", "int", "long", "float", "double", "string", ), "PrimitiveType", ) """ Names of salad data types (based on Avro schema declarations). Refer to the [Avro schema declaration documentation](https://avro.apache.org/docs/current/spec.html#schemas) for detailed information. null: no value boolean: a binary value int: 32-bit signed integer long: 64-bit signed integer float: single precision (32-bit) IEEE 754 floating-point number double: double precision (64-bit) IEEE 754 floating-point number string: Unicode character sequence """ AnyLoader = _EnumLoader(("Any",), "Any") """ The **Any** type validates for any non-null value. """ RecordFieldLoader = _RecordLoader(RecordField, None, None) RecordSchemaLoader = _RecordLoader(RecordSchema, None, None) EnumSchemaLoader = _RecordLoader(EnumSchema, None, None) ArraySchemaLoader = _RecordLoader(ArraySchema, None, None) MapSchemaLoader = _RecordLoader(MapSchema, None, None) UnionSchemaLoader = _RecordLoader(UnionSchema, None, None) CWLTypeLoader = _EnumLoader( ( "null", "boolean", "int", "long", "float", "double", "string", "File", "Directory", ), "CWLType", ) """ Extends primitive types with the concept of a file and directory as a builtin type. File: A File object Directory: A Directory object """ CWLArraySchemaLoader = _RecordLoader(CWLArraySchema, None, None) CWLRecordFieldLoader = _RecordLoader(CWLRecordField, None, None) CWLRecordSchemaLoader = _RecordLoader(CWLRecordSchema, None, None) FileLoader = _RecordLoader(File, None, None) DirectoryLoader = _RecordLoader(Directory, None, None) CWLObjectTypeLoader = _UnionLoader((), "CWLObjectTypeLoader") union_of_None_type_or_CWLObjectTypeLoader = _UnionLoader( ( None_type, CWLObjectTypeLoader, ) ) array_of_union_of_None_type_or_CWLObjectTypeLoader = _ArrayLoader( union_of_None_type_or_CWLObjectTypeLoader ) map_of_union_of_None_type_or_CWLObjectTypeLoader = _MapLoader( union_of_None_type_or_CWLObjectTypeLoader, "CWLInputFile", "@list", True ) CWLInputFileLoader = map_of_union_of_None_type_or_CWLObjectTypeLoader CWLVersionLoader = _EnumLoader( ( "draft-2", "draft-3.dev1", "draft-3.dev2", "draft-3.dev3", "draft-3.dev4", "draft-3.dev5", "draft-3", "draft-4.dev1", "draft-4.dev2", "draft-4.dev3", "v1.0.dev4", "v1.0", ), "CWLVersion", ) """ Version symbols for published CWL document versions. """ ExpressionLoader = _ExpressionLoader(str) InputRecordFieldLoader = _RecordLoader(InputRecordField, None, None) InputRecordSchemaLoader = _RecordLoader(InputRecordSchema, None, None) InputEnumSchemaLoader = _RecordLoader(InputEnumSchema, None, None) InputArraySchemaLoader = _RecordLoader(InputArraySchema, None, None) OutputRecordFieldLoader = _RecordLoader(OutputRecordField, None, None) OutputRecordSchemaLoader = _RecordLoader(OutputRecordSchema, None, None) OutputEnumSchemaLoader = _RecordLoader(OutputEnumSchema, None, None) OutputArraySchemaLoader = _RecordLoader(OutputArraySchema, None, None) InputParameterLoader = _RecordLoader(InputParameter, None, None) OutputParameterLoader = _RecordLoader(OutputParameter, None, None) InlineJavascriptRequirementLoader = _RecordLoader( InlineJavascriptRequirement, None, None ) SchemaDefRequirementLoader = _RecordLoader(SchemaDefRequirement, None, None) EnvironmentDefLoader = _RecordLoader(EnvironmentDef, None, None) CommandLineBindingLoader = _RecordLoader(CommandLineBinding, None, None) CommandOutputBindingLoader = _RecordLoader(CommandOutputBinding, None, None) CommandInputRecordFieldLoader = _RecordLoader(CommandInputRecordField, None, None) CommandInputRecordSchemaLoader = _RecordLoader(CommandInputRecordSchema, None, None) CommandInputEnumSchemaLoader = _RecordLoader(CommandInputEnumSchema, None, None) CommandInputArraySchemaLoader = _RecordLoader(CommandInputArraySchema, None, None) CommandOutputRecordFieldLoader = _RecordLoader(CommandOutputRecordField, None, None) CommandOutputRecordSchemaLoader = _RecordLoader(CommandOutputRecordSchema, None, None) CommandOutputEnumSchemaLoader = _RecordLoader(CommandOutputEnumSchema, None, None) CommandOutputArraySchemaLoader = _RecordLoader(CommandOutputArraySchema, None, None) CommandInputParameterLoader = _RecordLoader(CommandInputParameter, None, None) CommandOutputParameterLoader = _RecordLoader(CommandOutputParameter, None, None) stdoutLoader = _EnumLoader(("stdout",), "stdout") """ Only valid as a `type` for a `CommandLineTool` output with no `outputBinding` set. The following ``` outputs: an_output_name: type: stdout stdout: a_stdout_file ``` is equivalent to ``` outputs: an_output_name: type: File streamable: true outputBinding: glob: a_stdout_file stdout: a_stdout_file ``` If there is no `stdout` name provided, a random filename will be created. For example, the following ``` outputs: an_output_name: type: stdout ``` is equivalent to ``` outputs: an_output_name: type: File streamable: true outputBinding: glob: random_stdout_filenameABCDEFG stdout: random_stdout_filenameABCDEFG ``` """ stderrLoader = _EnumLoader(("stderr",), "stderr") """ Only valid as a `type` for a `CommandLineTool` output with no `outputBinding` set. The following ``` outputs: an_output_name: type: stderr stderr: a_stderr_file ``` is equivalent to ``` outputs: an_output_name: type: File streamable: true outputBinding: glob: a_stderr_file stderr: a_stderr_file ``` If there is no `stderr` name provided, a random filename will be created. For example, the following ``` outputs: an_output_name: type: stderr ``` is equivalent to ``` outputs: an_output_name: type: File streamable: true outputBinding: glob: random_stderr_filenameABCDEFG stderr: random_stderr_filenameABCDEFG ``` """ CommandLineToolLoader = _RecordLoader(CommandLineTool, None, None) DockerRequirementLoader = _RecordLoader(DockerRequirement, None, None) SoftwareRequirementLoader = _RecordLoader(SoftwareRequirement, None, None) SoftwarePackageLoader = _RecordLoader(SoftwarePackage, None, None) DirentLoader = _RecordLoader(Dirent, None, None) InitialWorkDirRequirementLoader = _RecordLoader(InitialWorkDirRequirement, None, None) EnvVarRequirementLoader = _RecordLoader(EnvVarRequirement, None, None) ShellCommandRequirementLoader = _RecordLoader(ShellCommandRequirement, None, None) ResourceRequirementLoader = _RecordLoader(ResourceRequirement, None, None) ExpressionToolOutputParameterLoader = _RecordLoader( ExpressionToolOutputParameter, None, None ) ExpressionToolLoader = _RecordLoader(ExpressionTool, None, None) LinkMergeMethodLoader = _EnumLoader( ( "merge_nested", "merge_flattened", ), "LinkMergeMethod", ) """ The input link merge method, described in [WorkflowStepInput](#WorkflowStepInput). """ WorkflowOutputParameterLoader = _RecordLoader(WorkflowOutputParameter, None, None) WorkflowStepInputLoader = _RecordLoader(WorkflowStepInput, None, None) WorkflowStepOutputLoader = _RecordLoader(WorkflowStepOutput, None, None) ScatterMethodLoader = _EnumLoader( ( "dotproduct", "nested_crossproduct", "flat_crossproduct", ), "ScatterMethod", ) """ The scatter method, as described in [workflow step scatter](#WorkflowStep). """ WorkflowStepLoader = _RecordLoader(WorkflowStep, None, None) WorkflowLoader = _RecordLoader(Workflow, None, None) SubworkflowFeatureRequirementLoader = _RecordLoader( SubworkflowFeatureRequirement, None, None ) ScatterFeatureRequirementLoader = _RecordLoader(ScatterFeatureRequirement, None, None) MultipleInputFeatureRequirementLoader = _RecordLoader( MultipleInputFeatureRequirement, None, None ) StepInputExpressionRequirementLoader = _RecordLoader( StepInputExpressionRequirement, None, None ) LoadListingRequirementLoader = _RecordLoader(LoadListingRequirement, None, None) InplaceUpdateRequirementLoader = _RecordLoader(InplaceUpdateRequirement, None, None) SecretsLoader = _RecordLoader(Secrets, None, None) TimeLimitLoader = _RecordLoader(TimeLimit, None, None) WorkReuseLoader = _RecordLoader(WorkReuse, None, None) NetworkAccessLoader = _RecordLoader(NetworkAccess, None, None) ProcessGeneratorLoader = _RecordLoader(ProcessGenerator, None, None) MPIRequirementLoader = _RecordLoader(MPIRequirement, None, None) CUDARequirementLoader = _RecordLoader(CUDARequirement, None, None) ShmSizeLoader = _RecordLoader(ShmSize, None, None) array_of_strtype = _ArrayLoader(strtype) union_of_None_type_or_strtype_or_array_of_strtype = _UnionLoader( ( None_type, strtype, array_of_strtype, ) ) uri_strtype_True_False_None_None = _URILoader(strtype, True, False, None, None) union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype = _UnionLoader( ( PrimitiveTypeLoader, RecordSchemaLoader, EnumSchemaLoader, ArraySchemaLoader, MapSchemaLoader, UnionSchemaLoader, strtype, ) ) array_of_union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype = _ArrayLoader( union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype ) union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype_or_array_of_union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype = _UnionLoader( ( PrimitiveTypeLoader, RecordSchemaLoader, EnumSchemaLoader, ArraySchemaLoader, MapSchemaLoader, UnionSchemaLoader, strtype, array_of_union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype, ) ) typedsl_union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype_or_array_of_union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype_2 = _TypeDSLLoader( union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype_or_array_of_union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype, 2, "v1.1", ) array_of_RecordFieldLoader = _ArrayLoader(RecordFieldLoader) union_of_None_type_or_array_of_RecordFieldLoader = _UnionLoader( ( None_type, array_of_RecordFieldLoader, ) ) idmap_fields_union_of_None_type_or_array_of_RecordFieldLoader = _IdMapLoader( union_of_None_type_or_array_of_RecordFieldLoader, "name", "type" ) Record_nameLoader = _EnumLoader(("record",), "Record_name") typedsl_Record_nameLoader_2 = _TypeDSLLoader(Record_nameLoader, 2, "v1.1") union_of_None_type_or_strtype = _UnionLoader( ( None_type, strtype, ) ) uri_union_of_None_type_or_strtype_True_False_None_None = _URILoader( union_of_None_type_or_strtype, True, False, None, None ) uri_array_of_strtype_True_False_None_None = _URILoader( array_of_strtype, True, False, None, None ) Enum_nameLoader = _EnumLoader(("enum",), "Enum_name") typedsl_Enum_nameLoader_2 = _TypeDSLLoader(Enum_nameLoader, 2, "v1.1") uri_union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype_or_array_of_union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype_False_True_2_None = _URILoader( union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype_or_array_of_union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype, False, True, 2, None, ) Array_nameLoader = _EnumLoader(("array",), "Array_name") typedsl_Array_nameLoader_2 = _TypeDSLLoader(Array_nameLoader, 2, "v1.1") Map_nameLoader = _EnumLoader(("map",), "Map_name") typedsl_Map_nameLoader_2 = _TypeDSLLoader(Map_nameLoader, 2, "v1.1") Union_nameLoader = _EnumLoader(("union",), "Union_name") typedsl_Union_nameLoader_2 = _TypeDSLLoader(Union_nameLoader, 2, "v1.1") union_of_PrimitiveTypeLoader_or_CWLRecordSchemaLoader_or_EnumSchemaLoader_or_CWLArraySchemaLoader_or_strtype = _UnionLoader( ( PrimitiveTypeLoader, CWLRecordSchemaLoader, EnumSchemaLoader, CWLArraySchemaLoader, strtype, ) ) array_of_union_of_PrimitiveTypeLoader_or_CWLRecordSchemaLoader_or_EnumSchemaLoader_or_CWLArraySchemaLoader_or_strtype = _ArrayLoader( union_of_PrimitiveTypeLoader_or_CWLRecordSchemaLoader_or_EnumSchemaLoader_or_CWLArraySchemaLoader_or_strtype ) union_of_PrimitiveTypeLoader_or_CWLRecordSchemaLoader_or_EnumSchemaLoader_or_CWLArraySchemaLoader_or_strtype_or_array_of_union_of_PrimitiveTypeLoader_or_CWLRecordSchemaLoader_or_EnumSchemaLoader_or_CWLArraySchemaLoader_or_strtype = _UnionLoader( ( PrimitiveTypeLoader, CWLRecordSchemaLoader, EnumSchemaLoader, CWLArraySchemaLoader, strtype, array_of_union_of_PrimitiveTypeLoader_or_CWLRecordSchemaLoader_or_EnumSchemaLoader_or_CWLArraySchemaLoader_or_strtype, ) ) uri_union_of_PrimitiveTypeLoader_or_CWLRecordSchemaLoader_or_EnumSchemaLoader_or_CWLArraySchemaLoader_or_strtype_or_array_of_union_of_PrimitiveTypeLoader_or_CWLRecordSchemaLoader_or_EnumSchemaLoader_or_CWLArraySchemaLoader_or_strtype_False_True_2_None = _URILoader( union_of_PrimitiveTypeLoader_or_CWLRecordSchemaLoader_or_EnumSchemaLoader_or_CWLArraySchemaLoader_or_strtype_or_array_of_union_of_PrimitiveTypeLoader_or_CWLRecordSchemaLoader_or_EnumSchemaLoader_or_CWLArraySchemaLoader_or_strtype, False, True, 2, None, ) typedsl_union_of_PrimitiveTypeLoader_or_CWLRecordSchemaLoader_or_EnumSchemaLoader_or_CWLArraySchemaLoader_or_strtype_or_array_of_union_of_PrimitiveTypeLoader_or_CWLRecordSchemaLoader_or_EnumSchemaLoader_or_CWLArraySchemaLoader_or_strtype_2 = _TypeDSLLoader( union_of_PrimitiveTypeLoader_or_CWLRecordSchemaLoader_or_EnumSchemaLoader_or_CWLArraySchemaLoader_or_strtype_or_array_of_union_of_PrimitiveTypeLoader_or_CWLRecordSchemaLoader_or_EnumSchemaLoader_or_CWLArraySchemaLoader_or_strtype, 2, "v1.1", ) array_of_CWLRecordFieldLoader = _ArrayLoader(CWLRecordFieldLoader) union_of_None_type_or_array_of_CWLRecordFieldLoader = _UnionLoader( ( None_type, array_of_CWLRecordFieldLoader, ) ) idmap_fields_union_of_None_type_or_array_of_CWLRecordFieldLoader = _IdMapLoader( union_of_None_type_or_array_of_CWLRecordFieldLoader, "name", "type" ) File_classLoader = _EnumLoader(("File",), "File_class") uri_File_classLoader_False_True_None_None = _URILoader( File_classLoader, False, True, None, None ) uri_union_of_None_type_or_strtype_False_False_None_None = _URILoader( union_of_None_type_or_strtype, False, False, None, None ) union_of_None_type_or_inttype = _UnionLoader( ( None_type, inttype, ) ) union_of_FileLoader_or_DirectoryLoader = _UnionLoader( ( FileLoader, DirectoryLoader, ) ) array_of_union_of_FileLoader_or_DirectoryLoader = _ArrayLoader( union_of_FileLoader_or_DirectoryLoader ) union_of_None_type_or_array_of_union_of_FileLoader_or_DirectoryLoader = _UnionLoader( ( None_type, array_of_union_of_FileLoader_or_DirectoryLoader, ) ) uri_union_of_None_type_or_strtype_True_False_None_True = _URILoader( union_of_None_type_or_strtype, True, False, None, True ) Directory_classLoader = _EnumLoader(("Directory",), "Directory_class") uri_Directory_classLoader_False_True_None_None = _URILoader( Directory_classLoader, False, True, None, None ) union_of_strtype_or_ExpressionLoader = _UnionLoader( ( strtype, ExpressionLoader, ) ) array_of_union_of_strtype_or_ExpressionLoader = _ArrayLoader( union_of_strtype_or_ExpressionLoader ) union_of_None_type_or_strtype_or_ExpressionLoader_or_array_of_union_of_strtype_or_ExpressionLoader = _UnionLoader( ( None_type, strtype, ExpressionLoader, array_of_union_of_strtype_or_ExpressionLoader, ) ) union_of_None_type_or_booltype = _UnionLoader( ( None_type, booltype, ) ) union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype = _UnionLoader( ( CWLTypeLoader, InputRecordSchemaLoader, InputEnumSchemaLoader, InputArraySchemaLoader, strtype, ) ) array_of_union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype = _ArrayLoader( union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype ) union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype = _UnionLoader( ( CWLTypeLoader, InputRecordSchemaLoader, InputEnumSchemaLoader, InputArraySchemaLoader, strtype, array_of_union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype, ) ) typedsl_union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype_2 = _TypeDSLLoader( union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype, 2, "v1.1", ) union_of_None_type_or_CommandLineBindingLoader = _UnionLoader( ( None_type, CommandLineBindingLoader, ) ) array_of_InputRecordFieldLoader = _ArrayLoader(InputRecordFieldLoader) union_of_None_type_or_array_of_InputRecordFieldLoader = _UnionLoader( ( None_type, array_of_InputRecordFieldLoader, ) ) idmap_fields_union_of_None_type_or_array_of_InputRecordFieldLoader = _IdMapLoader( union_of_None_type_or_array_of_InputRecordFieldLoader, "name", "type" ) uri_union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype_False_True_2_None = _URILoader( union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype, False, True, 2, None, ) union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype = _UnionLoader( ( CWLTypeLoader, OutputRecordSchemaLoader, OutputEnumSchemaLoader, OutputArraySchemaLoader, strtype, ) ) array_of_union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype = _ArrayLoader( union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype ) union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype = _UnionLoader( ( CWLTypeLoader, OutputRecordSchemaLoader, OutputEnumSchemaLoader, OutputArraySchemaLoader, strtype, array_of_union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype, ) ) typedsl_union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype_2 = _TypeDSLLoader( union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype, 2, "v1.1", ) union_of_None_type_or_CommandOutputBindingLoader = _UnionLoader( ( None_type, CommandOutputBindingLoader, ) ) array_of_OutputRecordFieldLoader = _ArrayLoader(OutputRecordFieldLoader) union_of_None_type_or_array_of_OutputRecordFieldLoader = _UnionLoader( ( None_type, array_of_OutputRecordFieldLoader, ) ) idmap_fields_union_of_None_type_or_array_of_OutputRecordFieldLoader = _IdMapLoader( union_of_None_type_or_array_of_OutputRecordFieldLoader, "name", "type" ) uri_union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype_False_True_2_None = _URILoader( union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype, False, True, 2, None, ) union_of_None_type_or_strtype_or_array_of_strtype_or_ExpressionLoader = _UnionLoader( ( None_type, strtype, array_of_strtype, ExpressionLoader, ) ) uri_union_of_None_type_or_strtype_or_array_of_strtype_or_ExpressionLoader_True_False_None_True = _URILoader( union_of_None_type_or_strtype_or_array_of_strtype_or_ExpressionLoader, True, False, None, True, ) union_of_None_type_or_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype = _UnionLoader( ( None_type, CWLTypeLoader, InputRecordSchemaLoader, InputEnumSchemaLoader, InputArraySchemaLoader, strtype, array_of_union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype, ) ) typedsl_union_of_None_type_or_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype_2 = _TypeDSLLoader( union_of_None_type_or_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype, 2, "v1.1", ) union_of_None_type_or_strtype_or_ExpressionLoader = _UnionLoader( ( None_type, strtype, ExpressionLoader, ) ) uri_union_of_None_type_or_strtype_or_ExpressionLoader_True_False_None_True = _URILoader( union_of_None_type_or_strtype_or_ExpressionLoader, True, False, None, True ) array_of_InputParameterLoader = _ArrayLoader(InputParameterLoader) idmap_inputs_array_of_InputParameterLoader = _IdMapLoader( array_of_InputParameterLoader, "id", "type" ) array_of_OutputParameterLoader = _ArrayLoader(OutputParameterLoader) idmap_outputs_array_of_OutputParameterLoader = _IdMapLoader( array_of_OutputParameterLoader, "id", "type" ) union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader_or_LoadListingRequirementLoader_or_InplaceUpdateRequirementLoader_or_SecretsLoader_or_TimeLimitLoader_or_WorkReuseLoader_or_NetworkAccessLoader_or_MPIRequirementLoader_or_CUDARequirementLoader_or_ShmSizeLoader = _UnionLoader( ( InlineJavascriptRequirementLoader, SchemaDefRequirementLoader, DockerRequirementLoader, SoftwareRequirementLoader, InitialWorkDirRequirementLoader, EnvVarRequirementLoader, ShellCommandRequirementLoader, ResourceRequirementLoader, SubworkflowFeatureRequirementLoader, ScatterFeatureRequirementLoader, MultipleInputFeatureRequirementLoader, StepInputExpressionRequirementLoader, LoadListingRequirementLoader, InplaceUpdateRequirementLoader, SecretsLoader, TimeLimitLoader, WorkReuseLoader, NetworkAccessLoader, MPIRequirementLoader, CUDARequirementLoader, ShmSizeLoader, ) ) array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader_or_LoadListingRequirementLoader_or_InplaceUpdateRequirementLoader_or_SecretsLoader_or_TimeLimitLoader_or_WorkReuseLoader_or_NetworkAccessLoader_or_MPIRequirementLoader_or_CUDARequirementLoader_or_ShmSizeLoader = _ArrayLoader( union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader_or_LoadListingRequirementLoader_or_InplaceUpdateRequirementLoader_or_SecretsLoader_or_TimeLimitLoader_or_WorkReuseLoader_or_NetworkAccessLoader_or_MPIRequirementLoader_or_CUDARequirementLoader_or_ShmSizeLoader ) union_of_None_type_or_array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader_or_LoadListingRequirementLoader_or_InplaceUpdateRequirementLoader_or_SecretsLoader_or_TimeLimitLoader_or_WorkReuseLoader_or_NetworkAccessLoader_or_MPIRequirementLoader_or_CUDARequirementLoader_or_ShmSizeLoader = _UnionLoader( ( None_type, array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader_or_LoadListingRequirementLoader_or_InplaceUpdateRequirementLoader_or_SecretsLoader_or_TimeLimitLoader_or_WorkReuseLoader_or_NetworkAccessLoader_or_MPIRequirementLoader_or_CUDARequirementLoader_or_ShmSizeLoader, ) ) idmap_requirements_union_of_None_type_or_array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader_or_LoadListingRequirementLoader_or_InplaceUpdateRequirementLoader_or_SecretsLoader_or_TimeLimitLoader_or_WorkReuseLoader_or_NetworkAccessLoader_or_MPIRequirementLoader_or_CUDARequirementLoader_or_ShmSizeLoader = _IdMapLoader( union_of_None_type_or_array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader_or_LoadListingRequirementLoader_or_InplaceUpdateRequirementLoader_or_SecretsLoader_or_TimeLimitLoader_or_WorkReuseLoader_or_NetworkAccessLoader_or_MPIRequirementLoader_or_CUDARequirementLoader_or_ShmSizeLoader, "class", "None", ) union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader_or_LoadListingRequirementLoader_or_InplaceUpdateRequirementLoader_or_SecretsLoader_or_TimeLimitLoader_or_WorkReuseLoader_or_NetworkAccessLoader_or_MPIRequirementLoader_or_CUDARequirementLoader_or_ShmSizeLoader_or_Any_type = _UnionLoader( ( InlineJavascriptRequirementLoader, SchemaDefRequirementLoader, DockerRequirementLoader, SoftwareRequirementLoader, InitialWorkDirRequirementLoader, EnvVarRequirementLoader, ShellCommandRequirementLoader, ResourceRequirementLoader, SubworkflowFeatureRequirementLoader, ScatterFeatureRequirementLoader, MultipleInputFeatureRequirementLoader, StepInputExpressionRequirementLoader, LoadListingRequirementLoader, InplaceUpdateRequirementLoader, SecretsLoader, TimeLimitLoader, WorkReuseLoader, NetworkAccessLoader, MPIRequirementLoader, CUDARequirementLoader, ShmSizeLoader, Any_type, ) ) array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader_or_LoadListingRequirementLoader_or_InplaceUpdateRequirementLoader_or_SecretsLoader_or_TimeLimitLoader_or_WorkReuseLoader_or_NetworkAccessLoader_or_MPIRequirementLoader_or_CUDARequirementLoader_or_ShmSizeLoader_or_Any_type = _ArrayLoader( union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader_or_LoadListingRequirementLoader_or_InplaceUpdateRequirementLoader_or_SecretsLoader_or_TimeLimitLoader_or_WorkReuseLoader_or_NetworkAccessLoader_or_MPIRequirementLoader_or_CUDARequirementLoader_or_ShmSizeLoader_or_Any_type ) union_of_None_type_or_array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader_or_LoadListingRequirementLoader_or_InplaceUpdateRequirementLoader_or_SecretsLoader_or_TimeLimitLoader_or_WorkReuseLoader_or_NetworkAccessLoader_or_MPIRequirementLoader_or_CUDARequirementLoader_or_ShmSizeLoader_or_Any_type = _UnionLoader( ( None_type, array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader_or_LoadListingRequirementLoader_or_InplaceUpdateRequirementLoader_or_SecretsLoader_or_TimeLimitLoader_or_WorkReuseLoader_or_NetworkAccessLoader_or_MPIRequirementLoader_or_CUDARequirementLoader_or_ShmSizeLoader_or_Any_type, ) ) idmap_hints_union_of_None_type_or_array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader_or_LoadListingRequirementLoader_or_InplaceUpdateRequirementLoader_or_SecretsLoader_or_TimeLimitLoader_or_WorkReuseLoader_or_NetworkAccessLoader_or_MPIRequirementLoader_or_CUDARequirementLoader_or_ShmSizeLoader_or_Any_type = _IdMapLoader( union_of_None_type_or_array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader_or_LoadListingRequirementLoader_or_InplaceUpdateRequirementLoader_or_SecretsLoader_or_TimeLimitLoader_or_WorkReuseLoader_or_NetworkAccessLoader_or_MPIRequirementLoader_or_CUDARequirementLoader_or_ShmSizeLoader_or_Any_type, "class", "None", ) union_of_None_type_or_CWLVersionLoader = _UnionLoader( ( None_type, CWLVersionLoader, ) ) uri_union_of_None_type_or_CWLVersionLoader_False_True_None_None = _URILoader( union_of_None_type_or_CWLVersionLoader, False, True, None, None ) InlineJavascriptRequirement_classLoader = _EnumLoader( ("InlineJavascriptRequirement",), "InlineJavascriptRequirement_class" ) uri_InlineJavascriptRequirement_classLoader_False_True_None_None = _URILoader( InlineJavascriptRequirement_classLoader, False, True, None, None ) union_of_None_type_or_array_of_strtype = _UnionLoader( ( None_type, array_of_strtype, ) ) SchemaDefRequirement_classLoader = _EnumLoader( ("SchemaDefRequirement",), "SchemaDefRequirement_class" ) uri_SchemaDefRequirement_classLoader_False_True_None_None = _URILoader( SchemaDefRequirement_classLoader, False, True, None, None ) union_of_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader = ( _UnionLoader( ( InputRecordSchemaLoader, InputEnumSchemaLoader, InputArraySchemaLoader, ) ) ) array_of_union_of_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader = _ArrayLoader( union_of_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader ) union_of_None_type_or_strtype_or_ExpressionLoader_or_array_of_strtype = _UnionLoader( ( None_type, strtype, ExpressionLoader, array_of_strtype, ) ) union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype = _UnionLoader( ( CWLTypeLoader, CommandInputRecordSchemaLoader, CommandInputEnumSchemaLoader, CommandInputArraySchemaLoader, strtype, ) ) array_of_union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype = _ArrayLoader( union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype ) union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype = _UnionLoader( ( CWLTypeLoader, CommandInputRecordSchemaLoader, CommandInputEnumSchemaLoader, CommandInputArraySchemaLoader, strtype, array_of_union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype, ) ) typedsl_union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype_2 = _TypeDSLLoader( union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype, 2, "v1.1", ) array_of_CommandInputRecordFieldLoader = _ArrayLoader(CommandInputRecordFieldLoader) union_of_None_type_or_array_of_CommandInputRecordFieldLoader = _UnionLoader( ( None_type, array_of_CommandInputRecordFieldLoader, ) ) idmap_fields_union_of_None_type_or_array_of_CommandInputRecordFieldLoader = ( _IdMapLoader( union_of_None_type_or_array_of_CommandInputRecordFieldLoader, "name", "type" ) ) uri_union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype_False_True_2_None = _URILoader( union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype, False, True, 2, None, ) union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype = _UnionLoader( ( CWLTypeLoader, CommandOutputRecordSchemaLoader, CommandOutputEnumSchemaLoader, CommandOutputArraySchemaLoader, strtype, ) ) array_of_union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype = _ArrayLoader( union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype ) union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype = _UnionLoader( ( CWLTypeLoader, CommandOutputRecordSchemaLoader, CommandOutputEnumSchemaLoader, CommandOutputArraySchemaLoader, strtype, array_of_union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype, ) ) typedsl_union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype_2 = _TypeDSLLoader( union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype, 2, "v1.1", ) array_of_CommandOutputRecordFieldLoader = _ArrayLoader(CommandOutputRecordFieldLoader) union_of_None_type_or_array_of_CommandOutputRecordFieldLoader = _UnionLoader( ( None_type, array_of_CommandOutputRecordFieldLoader, ) ) idmap_fields_union_of_None_type_or_array_of_CommandOutputRecordFieldLoader = ( _IdMapLoader( union_of_None_type_or_array_of_CommandOutputRecordFieldLoader, "name", "type" ) ) uri_union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype_False_True_2_None = _URILoader( union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype, False, True, 2, None, ) union_of_None_type_or_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype = _UnionLoader( ( None_type, CWLTypeLoader, CommandInputRecordSchemaLoader, CommandInputEnumSchemaLoader, CommandInputArraySchemaLoader, strtype, array_of_union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype, ) ) typedsl_union_of_None_type_or_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype_2 = _TypeDSLLoader( union_of_None_type_or_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype, 2, "v1.1", ) union_of_None_type_or_CWLTypeLoader_or_stdoutLoader_or_stderrLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype = _UnionLoader( ( None_type, CWLTypeLoader, stdoutLoader, stderrLoader, CommandOutputRecordSchemaLoader, CommandOutputEnumSchemaLoader, CommandOutputArraySchemaLoader, strtype, array_of_union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype, ) ) typedsl_union_of_None_type_or_CWLTypeLoader_or_stdoutLoader_or_stderrLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype_2 = _TypeDSLLoader( union_of_None_type_or_CWLTypeLoader_or_stdoutLoader_or_stderrLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype, 2, "v1.1", ) CommandLineTool_classLoader = _EnumLoader(("CommandLineTool",), "CommandLineTool_class") uri_CommandLineTool_classLoader_False_True_None_None = _URILoader( CommandLineTool_classLoader, False, True, None, None ) array_of_CommandInputParameterLoader = _ArrayLoader(CommandInputParameterLoader) idmap_inputs_array_of_CommandInputParameterLoader = _IdMapLoader( array_of_CommandInputParameterLoader, "id", "type" ) array_of_CommandOutputParameterLoader = _ArrayLoader(CommandOutputParameterLoader) idmap_outputs_array_of_CommandOutputParameterLoader = _IdMapLoader( array_of_CommandOutputParameterLoader, "id", "type" ) union_of_strtype_or_ExpressionLoader_or_CommandLineBindingLoader = _UnionLoader( ( strtype, ExpressionLoader, CommandLineBindingLoader, ) ) array_of_union_of_strtype_or_ExpressionLoader_or_CommandLineBindingLoader = ( _ArrayLoader(union_of_strtype_or_ExpressionLoader_or_CommandLineBindingLoader) ) union_of_None_type_or_array_of_union_of_strtype_or_ExpressionLoader_or_CommandLineBindingLoader = _UnionLoader( ( None_type, array_of_union_of_strtype_or_ExpressionLoader_or_CommandLineBindingLoader, ) ) array_of_inttype = _ArrayLoader(inttype) union_of_None_type_or_array_of_inttype = _UnionLoader( ( None_type, array_of_inttype, ) ) DockerRequirement_classLoader = _EnumLoader( ("DockerRequirement",), "DockerRequirement_class" ) uri_DockerRequirement_classLoader_False_True_None_None = _URILoader( DockerRequirement_classLoader, False, True, None, None ) SoftwareRequirement_classLoader = _EnumLoader( ("SoftwareRequirement",), "SoftwareRequirement_class" ) uri_SoftwareRequirement_classLoader_False_True_None_None = _URILoader( SoftwareRequirement_classLoader, False, True, None, None ) array_of_SoftwarePackageLoader = _ArrayLoader(SoftwarePackageLoader) idmap_packages_array_of_SoftwarePackageLoader = _IdMapLoader( array_of_SoftwarePackageLoader, "package", "specs" ) uri_union_of_None_type_or_array_of_strtype_False_False_None_True = _URILoader( union_of_None_type_or_array_of_strtype, False, False, None, True ) InitialWorkDirRequirement_classLoader = _EnumLoader( ("InitialWorkDirRequirement",), "InitialWorkDirRequirement_class" ) uri_InitialWorkDirRequirement_classLoader_False_True_None_None = _URILoader( InitialWorkDirRequirement_classLoader, False, True, None, None ) union_of_FileLoader_or_DirectoryLoader_or_DirentLoader_or_strtype_or_ExpressionLoader = _UnionLoader( ( FileLoader, DirectoryLoader, DirentLoader, strtype, ExpressionLoader, ) ) array_of_union_of_FileLoader_or_DirectoryLoader_or_DirentLoader_or_strtype_or_ExpressionLoader = _ArrayLoader( union_of_FileLoader_or_DirectoryLoader_or_DirentLoader_or_strtype_or_ExpressionLoader ) union_of_array_of_union_of_FileLoader_or_DirectoryLoader_or_DirentLoader_or_strtype_or_ExpressionLoader_or_strtype_or_ExpressionLoader = _UnionLoader( ( array_of_union_of_FileLoader_or_DirectoryLoader_or_DirentLoader_or_strtype_or_ExpressionLoader, strtype, ExpressionLoader, ) ) EnvVarRequirement_classLoader = _EnumLoader( ("EnvVarRequirement",), "EnvVarRequirement_class" ) uri_EnvVarRequirement_classLoader_False_True_None_None = _URILoader( EnvVarRequirement_classLoader, False, True, None, None ) array_of_EnvironmentDefLoader = _ArrayLoader(EnvironmentDefLoader) idmap_envDef_array_of_EnvironmentDefLoader = _IdMapLoader( array_of_EnvironmentDefLoader, "envName", "envValue" ) ShellCommandRequirement_classLoader = _EnumLoader( ("ShellCommandRequirement",), "ShellCommandRequirement_class" ) uri_ShellCommandRequirement_classLoader_False_True_None_None = _URILoader( ShellCommandRequirement_classLoader, False, True, None, None ) ResourceRequirement_classLoader = _EnumLoader( ("ResourceRequirement",), "ResourceRequirement_class" ) uri_ResourceRequirement_classLoader_False_True_None_None = _URILoader( ResourceRequirement_classLoader, False, True, None, None ) union_of_None_type_or_inttype_or_strtype_or_ExpressionLoader = _UnionLoader( ( None_type, inttype, strtype, ExpressionLoader, ) ) union_of_None_type_or_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype = _UnionLoader( ( None_type, CWLTypeLoader, OutputRecordSchemaLoader, OutputEnumSchemaLoader, OutputArraySchemaLoader, strtype, array_of_union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype, ) ) typedsl_union_of_None_type_or_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype_2 = _TypeDSLLoader( union_of_None_type_or_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype, 2, "v1.1", ) ExpressionTool_classLoader = _EnumLoader(("ExpressionTool",), "ExpressionTool_class") uri_ExpressionTool_classLoader_False_True_None_None = _URILoader( ExpressionTool_classLoader, False, True, None, None ) array_of_ExpressionToolOutputParameterLoader = _ArrayLoader( ExpressionToolOutputParameterLoader ) idmap_outputs_array_of_ExpressionToolOutputParameterLoader = _IdMapLoader( array_of_ExpressionToolOutputParameterLoader, "id", "type" ) uri_union_of_None_type_or_strtype_or_array_of_strtype_False_False_1_None = _URILoader( union_of_None_type_or_strtype_or_array_of_strtype, False, False, 1, None ) union_of_None_type_or_LinkMergeMethodLoader = _UnionLoader( ( None_type, LinkMergeMethodLoader, ) ) uri_union_of_None_type_or_strtype_or_array_of_strtype_False_False_2_None = _URILoader( union_of_None_type_or_strtype_or_array_of_strtype, False, False, 2, None ) array_of_WorkflowStepInputLoader = _ArrayLoader(WorkflowStepInputLoader) idmap_in__array_of_WorkflowStepInputLoader = _IdMapLoader( array_of_WorkflowStepInputLoader, "id", "source" ) union_of_strtype_or_WorkflowStepOutputLoader = _UnionLoader( ( strtype, WorkflowStepOutputLoader, ) ) array_of_union_of_strtype_or_WorkflowStepOutputLoader = _ArrayLoader( union_of_strtype_or_WorkflowStepOutputLoader ) union_of_array_of_union_of_strtype_or_WorkflowStepOutputLoader = _UnionLoader( (array_of_union_of_strtype_or_WorkflowStepOutputLoader,) ) uri_union_of_array_of_union_of_strtype_or_WorkflowStepOutputLoader_True_False_None_None = _URILoader( union_of_array_of_union_of_strtype_or_WorkflowStepOutputLoader, True, False, None, None, ) array_of_Any_type = _ArrayLoader(Any_type) union_of_None_type_or_array_of_Any_type = _UnionLoader( ( None_type, array_of_Any_type, ) ) idmap_hints_union_of_None_type_or_array_of_Any_type = _IdMapLoader( union_of_None_type_or_array_of_Any_type, "class", "None" ) union_of_strtype_or_CommandLineToolLoader_or_ExpressionToolLoader_or_WorkflowLoader_or_ProcessGeneratorLoader = _UnionLoader( ( strtype, CommandLineToolLoader, ExpressionToolLoader, WorkflowLoader, ProcessGeneratorLoader, ) ) uri_union_of_strtype_or_CommandLineToolLoader_or_ExpressionToolLoader_or_WorkflowLoader_or_ProcessGeneratorLoader_False_False_None_None = _URILoader( union_of_strtype_or_CommandLineToolLoader_or_ExpressionToolLoader_or_WorkflowLoader_or_ProcessGeneratorLoader, False, False, None, None, ) uri_union_of_None_type_or_strtype_or_array_of_strtype_False_False_0_None = _URILoader( union_of_None_type_or_strtype_or_array_of_strtype, False, False, 0, None ) union_of_None_type_or_ScatterMethodLoader = _UnionLoader( ( None_type, ScatterMethodLoader, ) ) uri_union_of_None_type_or_ScatterMethodLoader_False_True_None_None = _URILoader( union_of_None_type_or_ScatterMethodLoader, False, True, None, None ) Workflow_classLoader = _EnumLoader(("Workflow",), "Workflow_class") uri_Workflow_classLoader_False_True_None_None = _URILoader( Workflow_classLoader, False, True, None, None ) array_of_WorkflowOutputParameterLoader = _ArrayLoader(WorkflowOutputParameterLoader) idmap_outputs_array_of_WorkflowOutputParameterLoader = _IdMapLoader( array_of_WorkflowOutputParameterLoader, "id", "type" ) array_of_WorkflowStepLoader = _ArrayLoader(WorkflowStepLoader) union_of_array_of_WorkflowStepLoader = _UnionLoader((array_of_WorkflowStepLoader,)) idmap_steps_union_of_array_of_WorkflowStepLoader = _IdMapLoader( union_of_array_of_WorkflowStepLoader, "id", "None" ) SubworkflowFeatureRequirement_classLoader = _EnumLoader( ("SubworkflowFeatureRequirement",), "SubworkflowFeatureRequirement_class" ) uri_SubworkflowFeatureRequirement_classLoader_False_True_None_None = _URILoader( SubworkflowFeatureRequirement_classLoader, False, True, None, None ) ScatterFeatureRequirement_classLoader = _EnumLoader( ("ScatterFeatureRequirement",), "ScatterFeatureRequirement_class" ) uri_ScatterFeatureRequirement_classLoader_False_True_None_None = _URILoader( ScatterFeatureRequirement_classLoader, False, True, None, None ) MultipleInputFeatureRequirement_classLoader = _EnumLoader( ("MultipleInputFeatureRequirement",), "MultipleInputFeatureRequirement_class" ) uri_MultipleInputFeatureRequirement_classLoader_False_True_None_None = _URILoader( MultipleInputFeatureRequirement_classLoader, False, True, None, None ) StepInputExpressionRequirement_classLoader = _EnumLoader( ("StepInputExpressionRequirement",), "StepInputExpressionRequirement_class" ) uri_StepInputExpressionRequirement_classLoader_False_True_None_None = _URILoader( StepInputExpressionRequirement_classLoader, False, True, None, None ) uri_strtype_False_True_None_None = _URILoader(strtype, False, True, None, None) LoadListingEnumLoader = _EnumLoader( ( "no_listing", "shallow_listing", "deep_listing", ), "LoadListingEnum", ) union_of_LoadListingEnumLoader = _UnionLoader((LoadListingEnumLoader,)) uri_array_of_strtype_False_False_0_None = _URILoader( array_of_strtype, False, False, 0, None ) union_of_inttype_or_strtype = _UnionLoader( ( inttype, strtype, ) ) union_of_booltype_or_strtype = _UnionLoader( ( booltype, strtype, ) ) union_of_inttype_or_ExpressionLoader = _UnionLoader( ( inttype, ExpressionLoader, ) ) union_of_strtype_or_array_of_strtype = _UnionLoader( ( strtype, array_of_strtype, ) ) union_of_None_type_or_inttype_or_ExpressionLoader = _UnionLoader( ( None_type, inttype, ExpressionLoader, ) ) union_of_CommandLineToolLoader_or_ExpressionToolLoader_or_WorkflowLoader_or_ProcessGeneratorLoader = _UnionLoader( ( CommandLineToolLoader, ExpressionToolLoader, WorkflowLoader, ProcessGeneratorLoader, ) ) array_of_union_of_CommandLineToolLoader_or_ExpressionToolLoader_or_WorkflowLoader_or_ProcessGeneratorLoader = _ArrayLoader( union_of_CommandLineToolLoader_or_ExpressionToolLoader_or_WorkflowLoader_or_ProcessGeneratorLoader ) union_of_CommandLineToolLoader_or_ExpressionToolLoader_or_WorkflowLoader_or_ProcessGeneratorLoader_or_array_of_union_of_CommandLineToolLoader_or_ExpressionToolLoader_or_WorkflowLoader_or_ProcessGeneratorLoader = _UnionLoader( ( CommandLineToolLoader, ExpressionToolLoader, WorkflowLoader, ProcessGeneratorLoader, array_of_union_of_CommandLineToolLoader_or_ExpressionToolLoader_or_WorkflowLoader_or_ProcessGeneratorLoader, ) ) CWLObjectTypeLoader.add_loaders( ( booltype, inttype, floattype, strtype, FileLoader, DirectoryLoader, array_of_union_of_None_type_or_CWLObjectTypeLoader, map_of_union_of_None_type_or_CWLObjectTypeLoader, ) ) def load_document( doc: Any, baseuri: Optional[str] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> Any: if baseuri is None: baseuri = file_uri(os.getcwd()) + "/" if loadingOptions is None: loadingOptions = LoadingOptions() result, metadata = _document_load( union_of_CommandLineToolLoader_or_ExpressionToolLoader_or_WorkflowLoader_or_ProcessGeneratorLoader_or_array_of_union_of_CommandLineToolLoader_or_ExpressionToolLoader_or_WorkflowLoader_or_ProcessGeneratorLoader, doc, baseuri, loadingOptions, ) return result def load_document_with_metadata( doc: Any, baseuri: Optional[str] = None, loadingOptions: Optional[LoadingOptions] = None, addl_metadata_fields: Optional[MutableSequence[str]] = None, ) -> Any: if baseuri is None: baseuri = file_uri(os.getcwd()) + "/" if loadingOptions is None: loadingOptions = LoadingOptions(fileuri=baseuri) return _document_load( union_of_CommandLineToolLoader_or_ExpressionToolLoader_or_WorkflowLoader_or_ProcessGeneratorLoader_or_array_of_union_of_CommandLineToolLoader_or_ExpressionToolLoader_or_WorkflowLoader_or_ProcessGeneratorLoader, doc, baseuri, loadingOptions, addl_metadata_fields=addl_metadata_fields, ) def load_document_by_string( string: Any, uri: str, loadingOptions: Optional[LoadingOptions] = None, ) -> Any: yaml = yaml_no_ts() result = yaml.load(string) add_lc_filename(result, uri) if loadingOptions is None: loadingOptions = LoadingOptions(fileuri=uri) result, metadata = _document_load( union_of_CommandLineToolLoader_or_ExpressionToolLoader_or_WorkflowLoader_or_ProcessGeneratorLoader_or_array_of_union_of_CommandLineToolLoader_or_ExpressionToolLoader_or_WorkflowLoader_or_ProcessGeneratorLoader, result, uri, loadingOptions, ) return result def load_document_by_yaml( yaml: Any, uri: str, loadingOptions: Optional[LoadingOptions] = None, ) -> Any: """ Shortcut to load via a YAML object. yaml: must be from ruamel.yaml.main.YAML.load with preserve_quotes=True """ add_lc_filename(yaml, uri) if loadingOptions is None: loadingOptions = LoadingOptions(fileuri=uri) result, metadata = _document_load( union_of_CommandLineToolLoader_or_ExpressionToolLoader_or_WorkflowLoader_or_ProcessGeneratorLoader_or_array_of_union_of_CommandLineToolLoader_or_ExpressionToolLoader_or_WorkflowLoader_or_ProcessGeneratorLoader, yaml, uri, loadingOptions, ) return result cwl_utils-0.41/cwl_utils/parser/cwl_v1_0_utils.py0000644000000000000000000005103613615410400017075 0ustar00# SPDX-License-Identifier: Apache-2.0 import hashlib import logging from collections import namedtuple from collections.abc import MutableMapping, MutableSequence from io import StringIO from pathlib import Path from typing import IO, Any, cast from urllib.parse import urldefrag from schema_salad.exceptions import ValidationException from schema_salad.sourceline import SourceLine, add_lc_filename from schema_salad.utils import aslist, json_dumps, yaml_no_ts import cwl_utils.parser import cwl_utils.parser.cwl_v1_0 as cwl import cwl_utils.parser.utils from cwl_utils.errors import WorkflowException from cwl_utils.utils import yaml_dumps CONTENT_LIMIT: int = 64 * 1024 _logger = logging.getLogger("cwl_utils") SrcSink = namedtuple("SrcSink", ["src", "sink", "linkMerge", "message"]) def _compare_records( src: cwl.RecordSchema, sink: cwl.RecordSchema, strict: bool = False ) -> bool: """ Compare two records, ensuring they have compatible fields. This handles normalizing record names, which will be relative to workflow step, so that they can be compared. """ srcfields = {cwl.shortname(field.name): field.type_ for field in (src.fields or {})} sinkfields = { cwl.shortname(field.name): field.type_ for field in (sink.fields or {}) } for key in sinkfields.keys(): if ( not can_assign_src_to_sink( srcfields.get(key, "null"), sinkfields.get(key, "null"), strict ) and sinkfields.get(key) is not None ): _logger.info( "Record comparison failure for %s and %s\n" "Did not match fields for %s: %s and %s", cast(cwl.InputRecordSchema | cwl.CommandOutputRecordSchema, src).name, cast(cwl.InputRecordSchema | cwl.CommandOutputRecordSchema, sink).name, key, srcfields.get(key), sinkfields.get(key), ) return False return True def _compare_type(type1: Any, type2: Any) -> bool: match (type1, type1): case cwl.ArraySchema() as t1, cwl.ArraySchema() as t2: return _compare_type(t1.items, t2.items) case cwl.RecordSchema(), cwl.RecordSchema(): fields1 = { cwl.shortname(field.name): field.type_ for field in (type1.fields or {}) } fields2 = { cwl.shortname(field.name): field.type_ for field in (type2.fields or {}) } if fields1.keys() != fields2.keys(): return False return all(_compare_type(fields1[k], fields2[k]) for k in fields1.keys()) case MutableSequence(), MutableSequence(): if len(type1) != len(type2): return False for t3 in type1: if not any(_compare_type(t3, t2) for t2 in type2): return False return True return bool(type1 == type2) def _inputfile_load( doc: str | MutableMapping[str, Any] | MutableSequence[Any], baseuri: str, loadingOptions: cwl.LoadingOptions, addl_metadata_fields: MutableSequence[str] | None = None, ) -> tuple[Any, cwl.LoadingOptions]: loader = cwl.CWLInputFileLoader match doc: case str(): url = loadingOptions.fetcher.urljoin(baseuri, doc) if url in loadingOptions.idx: return loadingOptions.idx[url] doc_url, frg = urldefrag(url) text = loadingOptions.fetcher.fetch_text(doc_url) textIO = StringIO(text) textIO.name = doc_url yaml = yaml_no_ts() result = yaml.load(textIO) add_lc_filename(result, doc_url) loadingOptions = cwl.LoadingOptions( copyfrom=loadingOptions, fileuri=doc_url ) _inputfile_load( result, doc_url, loadingOptions, ) return loadingOptions.idx[url] case MutableMapping(): addl_metadata = {} if addl_metadata_fields is not None: for mf in addl_metadata_fields: if mf in doc: addl_metadata[mf] = doc[mf] loadingOptions = cwl.LoadingOptions( copyfrom=loadingOptions, baseuri=baseuri, addl_metadata=addl_metadata, ) loadingOptions.idx[baseuri] = ( loader.load(doc, baseuri, loadingOptions, docRoot=baseuri), loadingOptions, ) return loadingOptions.idx[baseuri] case MutableSequence(): loadingOptions.idx[baseuri] = ( loader.load(doc, baseuri, loadingOptions), loadingOptions, ) return loadingOptions.idx[baseuri] case _: raise ValidationException( "Expected URI string, MutableMapping or MutableSequence, got %s" % type(doc) ) def can_assign_src_to_sink(src: Any, sink: Any, strict: bool = False) -> bool: """ Check for identical type specifications, ignoring extra keys like inputBinding. src: admissible source types sink: admissible sink types In non-strict comparison, at least one source type must match one sink type, except for 'null'. In strict comparison, all source types must match at least one sink type. """ if "Any" in (src, sink): return True if isinstance(src, cwl.ArraySchema) and isinstance(sink, cwl.ArraySchema): return can_assign_src_to_sink(src.items, sink.items, strict) if isinstance(src, cwl.RecordSchema) and isinstance(sink, cwl.RecordSchema): return _compare_records(src, sink, strict) if isinstance(src, MutableSequence): if strict: for this_src in src: if not can_assign_src_to_sink(this_src, sink): return False return True for this_src in src: if this_src != "null" and can_assign_src_to_sink(this_src, sink): return True return False if isinstance(sink, MutableSequence): for this_sink in sink: if can_assign_src_to_sink(src, this_sink): return True return False return bool(src == sink) def check_all_types( src_dict: dict[str, Any], sinks: MutableSequence[cwl.WorkflowStepInput | cwl.WorkflowOutputParameter], type_dict: dict[str, Any], ) -> dict[str, list[SrcSink]]: """Given a list of sinks, check if their types match with the types of their sources.""" validation: dict[str, list[SrcSink]] = {"warning": [], "exception": []} for sink in sinks: match sink: case cwl.WorkflowOutputParameter(): sourceName = "outputSource" sourceField = sink.outputSource case cwl.WorkflowStepInput(): sourceName = "source" sourceField = sink.source case _: continue if sourceField is not None: if isinstance(sourceField, MutableSequence): linkMerge = sink.linkMerge or ( "merge_nested" if len(sourceField) > 1 else None ) srcs_of_sink = [] for parm_id in sourceField: srcs_of_sink += [src_dict[parm_id]] else: parm_id = cast(str, sourceField) if parm_id not in src_dict: raise SourceLine(sink, sourceName, ValidationException).makeError( f"{sourceName} not found: {parm_id}" ) srcs_of_sink = [src_dict[parm_id]] linkMerge = None for src in srcs_of_sink: check_result = check_types( type_dict[cast(str, src.id)], type_dict[sink.id], linkMerge, getattr(sink, "valueFrom", None), ) if check_result in ("warning", "exception"): validation[check_result].append(SrcSink(src, sink, linkMerge, None)) return validation def check_types( srctype: Any, sinktype: Any, linkMerge: str | None, valueFrom: str | None = None, ) -> str: """ Check if the source and sink types are correct. Acceptable types are "pass", "warning", or "exception". """ if valueFrom is not None: return "pass" if linkMerge is None: if can_assign_src_to_sink(srctype, sinktype, strict=True): return "pass" if can_assign_src_to_sink(srctype, sinktype, strict=False): return "warning" return "exception" if linkMerge == "merge_nested": return check_types( cwl.ArraySchema(items=srctype, type_="array"), sinktype, None, None ) if linkMerge == "merge_flattened": return check_types(merge_flatten_type(srctype), sinktype, None, None) raise ValidationException(f"Invalid value {linkMerge} for linkMerge field.") def content_limit_respected_read_bytes(f: IO[bytes]) -> bytes: """ Read file content up to 64 kB as a byte array. Truncate content for larger files. """ return f.read(CONTENT_LIMIT) def content_limit_respected_read(f: IO[bytes]) -> str: """ Read file content up to 64 kB as an utf-8 encoded string. Truncate content for larger files. """ return content_limit_respected_read_bytes(f).decode("utf-8") def convert_stdstreams_to_files(clt: cwl.CommandLineTool) -> None: """Convert stdout and stderr type shortcuts to files.""" for out in clt.outputs: if out.type_ == "stdout": if out.outputBinding is not None: raise ValidationException( "Not allowed to specify outputBinding when using stdout shortcut." ) if clt.stdout is None: clt.stdout = hashlib.sha1( # nosec json_dumps(clt.save(), sort_keys=True).encode("utf-8") ).hexdigest() out.type_ = "File" out.outputBinding = cwl.CommandOutputBinding(glob=clt.stdout) elif out.type_ == "stderr": if out.outputBinding is not None: raise ValidationException( "Not allowed to specify outputBinding when using stderr shortcut." ) if clt.stderr is None: clt.stderr = hashlib.sha1( # nosec json_dumps(clt.save(), sort_keys=True).encode("utf-8") ).hexdigest() out.type_ = "File" out.outputBinding = cwl.CommandOutputBinding(glob=clt.stderr) def load_inputfile( doc: Any, baseuri: str | None = None, loadingOptions: cwl.LoadingOptions | None = None, ) -> Any: """Load a CWL v1.0 input file from a serialized YAML string or a YAML object.""" if baseuri is None: baseuri = cwl.file_uri(str(Path.cwd())) + "/" if loadingOptions is None: loadingOptions = cwl.LoadingOptions() result, metadata = _inputfile_load( doc, baseuri, loadingOptions, ) return result def load_inputfile_by_string( string: Any, uri: str, loadingOptions: cwl.LoadingOptions | None = None, ) -> Any: """Load a CWL v1.0 input file from a serialized YAML string.""" result = yaml_no_ts().load(string) add_lc_filename(result, uri) if loadingOptions is None: loadingOptions = cwl.LoadingOptions(fileuri=uri) result, metadata = _inputfile_load( result, uri, loadingOptions, ) return result def load_inputfile_by_yaml( yaml: Any, uri: str, loadingOptions: cwl.LoadingOptions | None = None, ) -> Any: """Load a CWL v1.0 input file from a YAML object.""" add_lc_filename(yaml, uri) if loadingOptions is None: loadingOptions = cwl.LoadingOptions(fileuri=uri) result, metadata = _inputfile_load( yaml, uri, loadingOptions, ) return result def merge_flatten_type(src: Any) -> Any: """Return the merge flattened type of the source type.""" if isinstance(src, MutableSequence): return [merge_flatten_type(t) for t in src] if isinstance(src, cwl.ArraySchema): return src return cwl.ArraySchema(type_="array", items=src) def type_for_step_input( step: cwl.WorkflowStep, in_: cwl.WorkflowStepInput, ) -> Any: """Determine the type for the given step input.""" if in_.valueFrom is not None: return "Any" step_run = cwl_utils.parser.utils.load_step(step) cwl_utils.parser.utils.convert_stdstreams_to_files(step_run) if step_run and step_run.inputs: for step_input in step_run.inputs: if cast(str, step_input.id).split("#")[-1] == in_.id.split("#")[-1]: input_type = step_input.type_ if step.scatter is not None and in_.id in aslist(step.scatter): input_type = cwl.ArraySchema(items=input_type, type_="array") return input_type return "Any" def type_for_step_output( step: cwl.WorkflowStep, sourcename: str, ) -> Any: """Determine the type for the given step output.""" step_run = cwl_utils.parser.utils.load_step(step) cwl_utils.parser.utils.convert_stdstreams_to_files(step_run) if step_run and step_run.outputs: for step_output in step_run.outputs: if ( step_output.id.split("#")[-1].split("/")[-1] == sourcename.split("#")[-1].split("/")[-1] ): output_type = step_output.type_ if step.scatter is not None: if step.scatterMethod == "nested_crossproduct": for _ in range(len(aslist(step.scatter))): output_type = cwl.ArraySchema( items=output_type, type_="array" ) else: output_type = cwl.ArraySchema(items=output_type, type_="array") return output_type raise ValidationException( "param {} not found in {}.".format( sourcename, yaml_dumps(cwl.save(step)), ) ) def type_for_source( process: cwl.CommandLineTool | cwl.Workflow | cwl.ExpressionTool, sourcenames: str | list[str], parent: cwl.Workflow | None = None, linkMerge: str | None = None, ) -> Any: """Determine the type for the given sourcenames.""" scatter_context: list[tuple[int, str] | None] = [] params = param_for_source_id(process, sourcenames, parent, scatter_context) if not isinstance(params, MutableSequence): new_type = params.type_ if scatter_context[0] is not None: if scatter_context[0][1] == "nested_crossproduct": for _ in range(scatter_context[0][0]): new_type = cwl.ArraySchema(items=new_type, type_="array") else: new_type = cwl.ArraySchema(items=new_type, type_="array") if linkMerge == "merge_nested": new_type = cwl.ArraySchema(items=new_type, type_="array") elif linkMerge == "merge_flattened": new_type = merge_flatten_type(new_type) return new_type new_type = [] for p, sc in zip(params, scatter_context): if isinstance(p, str) and not any(_compare_type(t, p) for t in new_type): cur_type = p elif hasattr(p, "type_") and not any( _compare_type(t, p.type_) for t in new_type ): cur_type = p.type_ else: cur_type = None if cur_type is not None: if sc is not None: if sc[1] == "nested_crossproduct": for _ in range(sc[0]): cur_type = cwl.ArraySchema(items=cur_type, type_="array") else: cur_type = cwl.ArraySchema(items=cur_type, type_="array") new_type.append(cur_type) if len(new_type) == 1: new_type = new_type[0] if linkMerge == "merge_nested": return cwl.ArraySchema(items=new_type, type_="array") elif linkMerge == "merge_flattened": return merge_flatten_type(new_type) elif isinstance(sourcenames, list) and len(sourcenames) > 1: return cwl.ArraySchema(items=new_type, type_="array") return new_type def param_for_source_id( process: cwl.CommandLineTool | cwl.Workflow | cwl.ExpressionTool, sourcenames: str | list[str], parent: cwl.Workflow | None = None, scatter_context: list[tuple[int, str] | None] | None = None, ) -> ( cwl.InputParameter | cwl.CommandOutputParameter | MutableSequence[cwl.InputParameter | cwl.CommandOutputParameter] ): """Find the process input parameter that matches one of the given sourcenames.""" if isinstance(sourcenames, str): sourcenames = [sourcenames] params: MutableSequence[cwl.InputParameter | cwl.CommandOutputParameter] = [] for sourcename in sourcenames: if not isinstance(process, cwl.Workflow): for param in process.inputs: if param.id.split("#")[-1] == sourcename.split("#")[-1]: params.append(param) if scatter_context is not None: scatter_context.append(None) targets = [process] if parent: targets.append(parent) for target in targets: if isinstance(target, cwl.Workflow): for inp in target.inputs: if inp.id.split("#")[-1] == sourcename.split("#")[-1]: params.append(inp) if scatter_context is not None: scatter_context.append(None) for step in target.steps: if ( "/".join(sourcename.split("#")[-1].split("/")[:-1]) == step.id.split("#")[-1] and step.out ): step_run = cwl_utils.parser.utils.load_step(step) cwl_utils.parser.utils.convert_stdstreams_to_files(step_run) for outp in step.out: outp_id = outp if isinstance(outp, str) else outp.id if ( outp_id.split("#")[-1].split("/")[-1] == sourcename.split("#")[-1].split("/")[-1] ): if step_run and step_run.outputs: for output in step_run.outputs: if ( output.id.split("#")[-1].split("/")[-1] == sourcename.split("#")[-1].split("/")[-1] ): params.append(output) if scatter_context is not None: if isinstance(step.scatter, str): scatter_context.append( ( 1, step.scatterMethod or "dotproduct", ) ) elif isinstance( step.scatter, MutableSequence ): scatter_context.append( ( len(step.scatter), step.scatterMethod or "dotproduct", ) ) else: scatter_context.append(None) if len(params) == 1: return params[0] elif len(params) > 1: return params raise WorkflowException( "param {} not found in {}\n{}.".format( sourcename, yaml_dumps(cwl.save(process)), (f" or\n {yaml_dumps(cwl.save(parent))}" if parent is not None else ""), ) ) cwl_utils-0.41/cwl_utils/parser/cwl_v1_1.py0000644000000000000000000435634213615410400015672 0ustar00# # This file was autogenerated using schema-salad-tool --codegen=python # The code itself is released under the Apache 2.0 license and the help text is # subject to the license of the original schema. import copy import logging import os import pathlib import tempfile import uuid as _uuid__ # pylint: disable=unused-import # noqa: F401 import xml.sax # nosec from abc import ABC, abstractmethod from collections.abc import MutableMapping, MutableSequence, Sequence from io import StringIO from itertools import chain from typing import Any, Final, Optional, Union, cast from urllib.parse import quote, urldefrag, urlparse, urlsplit, urlunsplit from urllib.request import pathname2url from rdflib import Graph from rdflib.plugins.parsers.notation3 import BadSyntax from ruamel.yaml.comments import CommentedMap from schema_salad.exceptions import SchemaSaladException, ValidationException from schema_salad.fetcher import DefaultFetcher, Fetcher, MemoryCachingFetcher from schema_salad.sourceline import SourceLine, add_lc_filename from schema_salad.utils import CacheType, yaml_no_ts # requires schema-salad v8.2+ _vocab: dict[str, str] = {} _rvocab: dict[str, str] = {} _logger: Final = logging.getLogger("salad") IdxType = MutableMapping[str, tuple[Any, "LoadingOptions"]] class LoadingOptions: idx: Final[IdxType] fileuri: Final[Optional[str]] baseuri: Final[str] namespaces: Final[MutableMapping[str, str]] schemas: Final[MutableSequence[str]] original_doc: Final[Optional[Any]] addl_metadata: Final[MutableMapping[str, Any]] fetcher: Final[Fetcher] vocab: Final[dict[str, str]] rvocab: Final[dict[str, str]] cache: Final[CacheType] imports: Final[list[str]] includes: Final[list[str]] no_link_check: Final[Optional[bool]] container: Final[Optional[str]] def __init__( self, fetcher: Optional[Fetcher] = None, namespaces: Optional[dict[str, str]] = None, schemas: Optional[list[str]] = None, fileuri: Optional[str] = None, copyfrom: Optional["LoadingOptions"] = None, original_doc: Optional[Any] = None, addl_metadata: Optional[dict[str, str]] = None, baseuri: Optional[str] = None, idx: Optional[IdxType] = None, imports: Optional[list[str]] = None, includes: Optional[list[str]] = None, no_link_check: Optional[bool] = None, container: Optional[str] = None, ) -> None: """Create a LoadingOptions object.""" self.original_doc = original_doc if idx is not None: temp_idx = idx else: temp_idx = copyfrom.idx if copyfrom is not None else {} self.idx = temp_idx if fileuri is not None: temp_fileuri: Optional[str] = fileuri else: temp_fileuri = copyfrom.fileuri if copyfrom is not None else None self.fileuri = temp_fileuri if baseuri is not None: temp_baseuri = baseuri else: temp_baseuri = copyfrom.baseuri if copyfrom is not None else "" self.baseuri = temp_baseuri if namespaces is not None: temp_namespaces: MutableMapping[str, str] = namespaces else: temp_namespaces = copyfrom.namespaces if copyfrom is not None else {} self.namespaces = temp_namespaces if schemas is not None: temp_schemas: MutableSequence[str] = schemas else: temp_schemas = copyfrom.schemas if copyfrom is not None else [] self.schemas = temp_schemas if addl_metadata is not None: temp_addl_metadata: MutableMapping[str, Any] = addl_metadata else: temp_addl_metadata = copyfrom.addl_metadata if copyfrom is not None else {} self.addl_metadata = temp_addl_metadata if imports is not None: temp_imports = imports else: temp_imports = copyfrom.imports if copyfrom is not None else [] self.imports = temp_imports if includes is not None: temp_includes = includes else: temp_includes = copyfrom.includes if copyfrom is not None else [] self.includes = temp_includes if no_link_check is not None: temp_no_link_check: Optional[bool] = no_link_check else: temp_no_link_check = copyfrom.no_link_check if copyfrom is not None else False self.no_link_check = temp_no_link_check if container is not None: temp_container: Optional[str] = container else: temp_container = copyfrom.container if copyfrom is not None else None self.container = temp_container if fetcher is not None: temp_fetcher = fetcher elif copyfrom is not None: temp_fetcher = copyfrom.fetcher else: import requests from cachecontrol.caches import SeparateBodyFileCache from cachecontrol.wrapper import CacheControl root = pathlib.Path(os.environ.get("HOME", tempfile.gettempdir())) session = CacheControl( requests.Session(), cache=SeparateBodyFileCache(root / ".cache" / "salad"), ) temp_fetcher = DefaultFetcher({}, session) self.fetcher = temp_fetcher self.cache = self.fetcher.cache if isinstance(self.fetcher, MemoryCachingFetcher) else {} if self.namespaces != {}: temp_vocab = _vocab.copy() temp_rvocab = _rvocab.copy() for k, v in self.namespaces.items(): temp_vocab[k] = v temp_rvocab[v] = k else: temp_vocab = _vocab temp_rvocab = _rvocab self.vocab = temp_vocab self.rvocab = temp_rvocab @property def graph(self) -> Graph: """Generate a merged rdflib.Graph from all entries in self.schemas.""" graph = Graph() if not self.schemas: return graph key: Final = str(hash(tuple(self.schemas))) if key in self.cache: return cast(Graph, self.cache[key]) for schema in self.schemas: fetchurl = ( self.fetcher.urljoin(self.fileuri, schema) if self.fileuri is not None else pathlib.Path(schema).resolve().as_uri() ) if fetchurl not in self.cache or self.cache[fetchurl] is True: _logger.debug("Getting external schema %s", fetchurl) try: content = self.fetcher.fetch_text(fetchurl) except Exception as e: _logger.warning("Could not load extension schema %s: %s", fetchurl, str(e)) continue newGraph = Graph() err_msg = "unknown error" for fmt in ["xml", "turtle"]: try: newGraph.parse(data=content, format=fmt, publicID=str(fetchurl)) self.cache[fetchurl] = newGraph graph += newGraph break except (xml.sax.SAXParseException, TypeError, BadSyntax) as e: err_msg = str(e) else: _logger.warning("Could not load extension schema %s: %s", fetchurl, err_msg) self.cache[key] = graph return graph class Saveable(ABC): """Mark classes than have a save() and fromDoc() function.""" @classmethod @abstractmethod def fromDoc( cls, _doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None, ) -> "Saveable": """Construct this object from the result of yaml.load().""" @abstractmethod def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: """Convert this object to a JSON/YAML friendly dictionary.""" def load_field( val: Union[str, dict[str, str]], fieldtype: "_Loader", baseuri: str, loadingOptions: LoadingOptions, lc: Optional[list[Any]] = None, ) -> Any: """Load field.""" if isinstance(val, MutableMapping): if "$import" in val: if loadingOptions.fileuri is None: raise SchemaSaladException("Cannot load $import without fileuri") url1: Final = loadingOptions.fetcher.urljoin(loadingOptions.fileuri, val["$import"]) result, metadata = _document_load_by_url( fieldtype, url1, loadingOptions, ) loadingOptions.imports.append(url1) return result if "$include" in val: if loadingOptions.fileuri is None: raise SchemaSaladException("Cannot load $import without fileuri") url2: Final = loadingOptions.fetcher.urljoin(loadingOptions.fileuri, val["$include"]) val = loadingOptions.fetcher.fetch_text(url2) loadingOptions.includes.append(url2) return fieldtype.load(val, baseuri, loadingOptions, lc=lc) save_type = Optional[Union[MutableMapping[str, Any], MutableSequence[Any], int, float, bool, str]] def extract_type(val_type: type[Any]) -> str: """Take a type of value, and extracts the value as a string.""" val_str: Final = str(val_type) return val_str.split("'")[1] def convert_typing(val_type: str) -> str: """Normalize type names to schema-salad types.""" if "None" in val_type: return "null" if "CommentedSeq" in val_type or "list" in val_type: return "array" if "CommentedMap" in val_type or "dict" in val_type: return "object" if "False" in val_type or "True" in val_type: return "boolean" return val_type def parse_errors(error_message: str) -> tuple[str, str, str]: """Parse error messages from several loaders into one error message.""" if not error_message.startswith("Expected"): return error_message, "", "" vals: Final = error_message.split("\n") if len(vals) == 1: return error_message, "", "" types1: Final = set() for val in vals: individual_vals = val.split(" ") if val == "": continue if individual_vals[1] == "one": individual_vals = val.split("(")[1].split(",") for t in individual_vals: types1.add(t.strip(" ").strip(")\n")) elif individual_vals[2] == "").replace("'", "")) elif individual_vals[0] == "Value": types1.add(individual_vals[-1].strip(".")) else: types1.add(individual_vals[1].replace(",", "")) types2: Final = {val for val in types1 if val != "NoneType"} if "str" in types2: types3 = {convert_typing(val) for val in types2 if "'" not in val} else: types3 = types2 to_print = "" for val in types3: if "'" in val: to_print = "value" if len(types3) == 1 else "values" if to_print == "": to_print = "type" if len(types3) == 1 else "types" verb_tensage: Final = "is" if len(types3) == 1 else "are" return str(types3).replace("{", "(").replace("}", ")").replace("'", ""), to_print, verb_tensage def save( val: Any, top: bool = True, base_url: str = "", relative_uris: bool = True, ) -> save_type: if isinstance(val, Saveable): return val.save(top=top, base_url=base_url, relative_uris=relative_uris) if isinstance(val, MutableSequence): return [save(v, top=False, base_url=base_url, relative_uris=relative_uris) for v in val] if isinstance(val, MutableMapping): newdict: Final = {} for key in val: newdict[key] = save(val[key], top=False, base_url=base_url, relative_uris=relative_uris) return newdict if val is None or isinstance(val, (int, float, bool, str)): return val raise Exception("Not Saveable: %s" % type(val)) def save_with_metadata( val: Any, valLoadingOpts: LoadingOptions, top: bool = True, base_url: str = "", relative_uris: bool = True, ) -> save_type: """Save and set $namespaces, $schemas, $base and any other metadata fields at the top level.""" saved_val: Final = save(val, top, base_url, relative_uris) newdict: MutableMapping[str, Any] = {} if isinstance(saved_val, MutableSequence): newdict = {"$graph": saved_val} elif isinstance(saved_val, MutableMapping): newdict = saved_val if valLoadingOpts.namespaces: newdict["$namespaces"] = valLoadingOpts.namespaces if valLoadingOpts.schemas: newdict["$schemas"] = valLoadingOpts.schemas if valLoadingOpts.baseuri: newdict["$base"] = valLoadingOpts.baseuri for k, v in valLoadingOpts.addl_metadata.items(): if k not in newdict: newdict[k] = v return newdict def expand_url( url: str, base_url: str, loadingOptions: LoadingOptions, scoped_id: bool = False, vocab_term: bool = False, scoped_ref: Optional[int] = None, ) -> str: if url in ("@id", "@type"): return url if vocab_term and url in loadingOptions.vocab: return url if bool(loadingOptions.vocab) and ":" in url: prefix: Final = url.split(":")[0] if prefix in loadingOptions.vocab: url = loadingOptions.vocab[prefix] + url[len(prefix) + 1 :] split1: Final = urlsplit(url) if ( (bool(split1.scheme) and split1.scheme in loadingOptions.fetcher.supported_schemes()) or url.startswith("$(") or url.startswith("${") ): pass elif scoped_id and not bool(split1.fragment): splitbase1: Final = urlsplit(base_url) frg: str if bool(splitbase1.fragment): frg = splitbase1.fragment + "/" + split1.path else: frg = split1.path pt: Final = splitbase1.path if splitbase1.path != "" else "/" url = urlunsplit((splitbase1.scheme, splitbase1.netloc, pt, splitbase1.query, frg)) elif scoped_ref is not None and not bool(split1.fragment): splitbase2: Final = urlsplit(base_url) sp = splitbase2.fragment.split("/") n = scoped_ref while n > 0 and len(sp) > 0: sp.pop() n -= 1 sp.append(url) url = urlunsplit( ( splitbase2.scheme, splitbase2.netloc, splitbase2.path, splitbase2.query, "/".join(sp), ) ) else: url = loadingOptions.fetcher.urljoin(base_url, url) if vocab_term: split2: Final = urlsplit(url) if bool(split2.scheme): if url in loadingOptions.rvocab: return loadingOptions.rvocab[url] else: raise ValidationException(f"Term {url!r} not in vocabulary") return url class _Loader: def load( self, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None, lc: Optional[list[Any]] = None, ) -> Any: pass class _AnyLoader(_Loader): def load( self, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None, lc: Optional[list[Any]] = None, ) -> Any: if doc is not None: return doc raise ValidationException("Expected non-null") class _PrimitiveLoader(_Loader): def __init__(self, tp: Union[type, tuple[type[str], type[str]]]) -> None: self.tp: Final = tp def load( self, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None, lc: Optional[list[Any]] = None, ) -> Any: if not isinstance(doc, self.tp): raise ValidationException(f"Expected a {self.tp} but got {doc.__class__.__name__}") return doc def __repr__(self) -> str: return str(self.tp) class _ArrayLoader(_Loader): def __init__(self, items: _Loader) -> None: self.items: Final = items def load( self, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None, lc: Optional[list[Any]] = None, ) -> Any: if not isinstance(doc, MutableSequence): raise ValidationException( f"Value is a {convert_typing(extract_type(type(doc)))}, " f"but valid type for this field is an array." ) r: Final[list[Any]] = [] errors: Final[list[SchemaSaladException]] = [] fields: Final[list[str]] = [] for i in range(0, len(doc)): try: lf = load_field( doc[i], _UnionLoader([self, self.items]), baseuri, loadingOptions, lc=lc ) flatten = loadingOptions.container != "@list" if flatten and isinstance(lf, MutableSequence): r.extend(lf) else: r.append(lf) if isinstance(doc[i], CommentedMap): if doc[i].get("id") is not None: if doc[i].get("id") in fields: errors.append( ValidationException( f"Duplicate field {doc[i].get('id')!r}", SourceLine(doc[i], "id", str), [], ) ) else: fields.append(doc[i].get("id")) except ValidationException as e: e = ValidationException( "array item is invalid because", SourceLine(doc, i, str), [e] ) errors.append(e) if errors: raise ValidationException("", None, errors) return r def __repr__(self) -> str: return f"array<{self.items}>" class _MapLoader(_Loader): def __init__( self, values: _Loader, name: Optional[str] = None, container: Optional[str] = None, no_link_check: Optional[bool] = None, ) -> None: self.values: Final = values self.name: Final = name self.container: Final = container self.no_link_check: Final = no_link_check def load( self, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None, lc: Optional[list[Any]] = None, ) -> Any: if not isinstance(doc, MutableMapping): raise ValidationException(f"Expected a map, was {type(doc)}") if self.container is not None or self.no_link_check is not None: loadingOptions = LoadingOptions( copyfrom=loadingOptions, container=self.container, no_link_check=self.no_link_check ) r: Final[dict[str, Any]] = {} errors: Final[list[SchemaSaladException]] = [] for k, v in doc.items(): try: lf = load_field(v, self.values, baseuri, loadingOptions, lc) r[k] = lf except ValidationException as e: errors.append(e.with_sourceline(SourceLine(doc, k, str))) if errors: raise ValidationException("", None, errors) return r def __repr__(self) -> str: return self.name if self.name is not None else f"map" class _EnumLoader(_Loader): def __init__(self, symbols: Sequence[str], name: str) -> None: self.symbols: Final = symbols self.name: Final = name def load( self, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None, lc: Optional[list[Any]] = None, ) -> Any: if doc in self.symbols: return doc raise ValidationException(f"Expected one of {self.symbols}") def __repr__(self) -> str: return self.name class _SecondaryDSLLoader(_Loader): def __init__(self, inner: _Loader) -> None: self.inner: Final = inner def load( self, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None, lc: Optional[list[Any]] = None, ) -> Any: r: Final[list[dict[str, Any]]] = [] if isinstance(doc, MutableSequence): for d in doc: if isinstance(d, str): if d.endswith("?"): r.append({"pattern": d[:-1], "required": False}) else: r.append({"pattern": d}) elif isinstance(d, dict): new_dict1: dict[str, Any] = {} dict_copy = copy.deepcopy(d) if "pattern" in dict_copy: new_dict1["pattern"] = dict_copy.pop("pattern") else: raise ValidationException( f"Missing pattern in secondaryFiles specification entry: {d}" ) new_dict1["required"] = ( dict_copy.pop("required") if "required" in dict_copy else None ) if len(dict_copy): raise ValidationException( "Unallowed values in secondaryFiles specification entry: {}".format( dict_copy ) ) r.append(new_dict1) else: raise ValidationException( "Expected a string or sequence of (strings or mappings)." ) elif isinstance(doc, MutableMapping): new_dict2: Final = {} doc_copy: Final = copy.deepcopy(doc) if "pattern" in doc_copy: new_dict2["pattern"] = doc_copy.pop("pattern") else: raise ValidationException( f"Missing pattern in secondaryFiles specification entry: {doc}" ) new_dict2["required"] = doc_copy.pop("required") if "required" in doc_copy else None if len(doc_copy): raise ValidationException( f"Unallowed values in secondaryFiles specification entry: {doc_copy}" ) r.append(new_dict2) elif isinstance(doc, str): if doc.endswith("?"): r.append({"pattern": doc[:-1], "required": False}) else: r.append({"pattern": doc}) else: raise ValidationException("Expected str or sequence of str") return self.inner.load(r, baseuri, loadingOptions, docRoot, lc=lc) class _RecordLoader(_Loader): def __init__( self, classtype: type[Saveable], container: Optional[str] = None, no_link_check: Optional[bool] = None, ) -> None: self.classtype: Final = classtype self.container: Final = container self.no_link_check: Final = no_link_check def load( self, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None, lc: Optional[list[Any]] = None, ) -> Any: if not isinstance(doc, MutableMapping): raise ValidationException( f"Value is a {convert_typing(extract_type(type(doc)))}, " f"but valid type for this field is an object." ) if self.container is not None or self.no_link_check is not None: loadingOptions = LoadingOptions( copyfrom=loadingOptions, container=self.container, no_link_check=self.no_link_check ) return self.classtype.fromDoc(doc, baseuri, loadingOptions, docRoot=docRoot) def __repr__(self) -> str: return str(self.classtype.__name__) class _ExpressionLoader(_Loader): def __init__(self, items: type[str]) -> None: self.items: Final = items def load( self, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None, lc: Optional[list[Any]] = None, ) -> Any: if not isinstance(doc, str): raise ValidationException( f"Value is a {convert_typing(extract_type(type(doc)))}, " f"but valid type for this field is a str." ) return doc class _UnionLoader(_Loader): def __init__(self, alternates: Sequence[_Loader], name: Optional[str] = None) -> None: self.alternates = alternates self.name: Final = name def add_loaders(self, loaders: Sequence[_Loader]) -> None: self.alternates = tuple(loader for loader in chain(self.alternates, loaders)) def load( self, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None, lc: Optional[list[Any]] = None, ) -> Any: errors: Final = [] if lc is None: lc = [] for t in self.alternates: try: return t.load(doc, baseuri, loadingOptions, docRoot=docRoot, lc=lc) except ValidationException as e: if isinstance(t, _ArrayLoader) and len(self.alternates) > 1: continue if isinstance(doc, (CommentedMap, dict)): if "class" in doc: if str(doc.get("class")) == str(t): errors.append( ValidationException( f"Object `{baseuri.split('/')[-1]}` is not valid because:", SourceLine(doc, next(iter(doc)), str), [e], ) ) else: if "array" in str(t): continue else: if "id" in doc: id = baseuri.split("/")[-1] + "#" + str(doc.get("id")) if "id" in lc: errors.append( ValidationException( f"checking object `{id}` using `{t}`", SourceLine(lc, "id", str), [e], ) ) else: errors.append( ValidationException( f"checking object `{id}` using `{t}`", SourceLine(lc, doc.get("id"), str), [e], ) ) else: if not isinstance( t, (_PrimitiveLoader) ): # avoids 'tried was {x}' errors errors.append( ValidationException(f"tried `{t}` but", None, [e]) ) else: # avoids "tried but x" and instead returns the values for parsing errors.append(ValidationException("", None, [e])) if isinstance(doc, (CommentedMap, dict)) and "class" in doc: if str(doc.get("class")) not in str(self.alternates): errors.append( ValidationException( "Field `class` contains undefined reference to " + "`" + "/".join(baseuri.split("/")[0:-1]) + "/" + str(doc.get("class")) + "`", SourceLine(doc, "class", str), [], ) ) raise ValidationException("", None, errors, "*") def __repr__(self) -> str: return self.name if self.name is not None else " | ".join(str(a) for a in self.alternates) class _URILoader(_Loader): def __init__( self, inner: _Loader, scoped_id: bool, vocab_term: bool, scoped_ref: Optional[int], no_link_check: Optional[bool], ) -> None: self.inner: Final = inner self.scoped_id: Final = scoped_id self.vocab_term: Final = vocab_term self.scoped_ref: Final = scoped_ref self.no_link_check: Final = no_link_check def load( self, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None, lc: Optional[list[Any]] = None, ) -> Any: if self.no_link_check is not None: loadingOptions = LoadingOptions( copyfrom=loadingOptions, no_link_check=self.no_link_check ) if isinstance(doc, MutableSequence): newdoc: Final = [] for i in doc: if isinstance(i, str): newdoc.append( expand_url( i, baseuri, loadingOptions, self.scoped_id, self.vocab_term, self.scoped_ref, ) ) else: newdoc.append(i) doc = newdoc elif isinstance(doc, str): doc = expand_url( doc, baseuri, loadingOptions, self.scoped_id, self.vocab_term, self.scoped_ref, ) if isinstance(doc, str): if not loadingOptions.no_link_check: errors: Final = [] try: if not loadingOptions.fetcher.check_exists(doc): errors.append( ValidationException(f"contains undefined reference to `{doc}`") ) except ValidationException: pass if len(errors) > 0: raise ValidationException("", None, errors) return self.inner.load(doc, baseuri, loadingOptions, lc=lc) class _TypeDSLLoader(_Loader): def __init__(self, inner: _Loader, refScope: Optional[int], salad_version: str) -> None: self.inner: Final = inner self.refScope: Final = refScope self.salad_version: Final = salad_version def resolve( self, doc: str, baseuri: str, loadingOptions: LoadingOptions, ) -> Union[list[Union[dict[str, Any], str]], dict[str, Any], str]: doc_ = doc optional = False if doc_.endswith("?"): optional = True doc_ = doc_[0:-1] if doc_.endswith("[]"): salad_versions: Final = [int(v) for v in self.salad_version[1:].split(".")] items: Union[list[Union[dict[str, Any], str]], dict[str, Any], str] = "" rest: Final = doc_[0:-2] if salad_versions < [1, 3]: if rest.endswith("[]"): # To show the error message with the original type return doc else: items = expand_url(rest, baseuri, loadingOptions, False, True, self.refScope) else: items = self.resolve(rest, baseuri, loadingOptions) if isinstance(items, str): items = expand_url(items, baseuri, loadingOptions, False, True, self.refScope) expanded: Union[dict[str, Any], str] = {"type": "array", "items": items} else: expanded = expand_url(doc_, baseuri, loadingOptions, False, True, self.refScope) if optional: return ["null", expanded] else: return expanded def load( self, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None, lc: Optional[list[Any]] = None, ) -> Any: if isinstance(doc, MutableSequence): r: Final[list[Any]] = [] for d in doc: if isinstance(d, str): resolved = self.resolve(d, baseuri, loadingOptions) if isinstance(resolved, MutableSequence): for i in resolved: if i not in r: r.append(i) else: if resolved not in r: r.append(resolved) else: r.append(d) doc = r elif isinstance(doc, str): doc = self.resolve(doc, baseuri, loadingOptions) return self.inner.load(doc, baseuri, loadingOptions, lc=lc) class _IdMapLoader(_Loader): def __init__(self, inner: _Loader, mapSubject: str, mapPredicate: Optional[str]) -> None: self.inner: Final = inner self.mapSubject: Final = mapSubject self.mapPredicate: Final = mapPredicate def load( self, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None, lc: Optional[list[Any]] = None, ) -> Any: if isinstance(doc, MutableMapping): r: Final[list[Any]] = [] for k in doc.keys(): val = doc[k] if isinstance(val, CommentedMap): v = copy.copy(val) v.lc.data = val.lc.data v.lc.filename = val.lc.filename v[self.mapSubject] = k r.append(v) elif isinstance(val, MutableMapping): v2 = copy.copy(val) v2[self.mapSubject] = k r.append(v2) else: if self.mapPredicate: v3 = {self.mapPredicate: val} v3[self.mapSubject] = k r.append(v3) else: raise ValidationException("No mapPredicate") doc = r return self.inner.load(doc, baseuri, loadingOptions, lc=lc) def _document_load( loader: _Loader, doc: Union[str, MutableMapping[str, Any], MutableSequence[Any]], baseuri: str, loadingOptions: LoadingOptions, addl_metadata_fields: Optional[MutableSequence[str]] = None, ) -> tuple[Any, LoadingOptions]: if isinstance(doc, str): return _document_load_by_url( loader, loadingOptions.fetcher.urljoin(baseuri, doc), loadingOptions, addl_metadata_fields=addl_metadata_fields, ) if isinstance(doc, MutableMapping): addl_metadata: Final = {} if addl_metadata_fields is not None: for mf in addl_metadata_fields: if mf in doc: addl_metadata[mf] = doc[mf] docuri: Final = baseuri if "$base" in doc: baseuri = doc["$base"] loadingOptions = LoadingOptions( copyfrom=loadingOptions, namespaces=doc.get("$namespaces", None), schemas=doc.get("$schemas", None), baseuri=doc.get("$base", None), addl_metadata=addl_metadata, ) doc2: Final = copy.copy(doc) if "$namespaces" in doc2: doc2.pop("$namespaces") if "$schemas" in doc2: doc2.pop("$schemas") if "$base" in doc2: doc2.pop("$base") if "$graph" in doc2: loadingOptions.idx[baseuri] = ( loader.load(doc2["$graph"], baseuri, loadingOptions), loadingOptions, ) else: loadingOptions.idx[baseuri] = ( loader.load(doc2, baseuri, loadingOptions, docRoot=baseuri), loadingOptions, ) if docuri != baseuri: loadingOptions.idx[docuri] = loadingOptions.idx[baseuri] return loadingOptions.idx[baseuri] if isinstance(doc, MutableSequence): loadingOptions.idx[baseuri] = ( loader.load(doc, baseuri, loadingOptions), loadingOptions, ) return loadingOptions.idx[baseuri] raise ValidationException( "Expected URI string, MutableMapping or MutableSequence, got %s" % type(doc) ) def _document_load_by_url( loader: _Loader, url: str, loadingOptions: LoadingOptions, addl_metadata_fields: Optional[MutableSequence[str]] = None, ) -> tuple[Any, LoadingOptions]: if url in loadingOptions.idx: return loadingOptions.idx[url] doc_url, frg = urldefrag(url) text: Final = loadingOptions.fetcher.fetch_text(doc_url) textIO: Final = StringIO(text) textIO.name = str(doc_url) yaml: Final = yaml_no_ts() result: Final = yaml.load(textIO) add_lc_filename(result, doc_url) loadingOptions = LoadingOptions(copyfrom=loadingOptions, fileuri=doc_url) _document_load( loader, result, doc_url, loadingOptions, addl_metadata_fields=addl_metadata_fields, ) return loadingOptions.idx[url] def file_uri(path: str, split_frag: bool = False) -> str: """Transform a file path into a URL with file scheme.""" if path.startswith("file://"): return path if split_frag: pathsp: Final = path.split("#", 2) frag = "#" + quote(str(pathsp[1])) if len(pathsp) == 2 else "" urlpath = pathname2url(str(pathsp[0])) else: urlpath = pathname2url(path) frag = "" if urlpath.startswith("//"): return f"file:{urlpath}{frag}" return f"file://{urlpath}{frag}" def prefix_url(url: str, namespaces: dict[str, str]) -> str: """Expand short forms into full URLs using the given namespace dictionary.""" for k, v in namespaces.items(): if url.startswith(v): return k + ":" + url[len(v) :] return url def save_relative_uri( uri: Any, base_url: str, scoped_id: bool, ref_scope: Optional[int], relative_uris: bool, ) -> Any: """Convert any URI to a relative one, obeying the scoping rules.""" if isinstance(uri, MutableSequence): return [save_relative_uri(u, base_url, scoped_id, ref_scope, relative_uris) for u in uri] elif isinstance(uri, str): if not relative_uris or uri == base_url: return uri urisplit: Final = urlsplit(uri) basesplit: Final = urlsplit(base_url) if urisplit.scheme == basesplit.scheme and urisplit.netloc == basesplit.netloc: if urisplit.path != basesplit.path: p = os.path.relpath(urisplit.path, os.path.dirname(basesplit.path)) if urisplit.fragment: p = p + "#" + urisplit.fragment return p basefrag = basesplit.fragment + "/" if ref_scope: sp = basefrag.split("/") i = 0 while i < ref_scope: sp.pop() i += 1 basefrag = "/".join(sp) if urisplit.fragment.startswith(basefrag): return urisplit.fragment[len(basefrag) :] return urisplit.fragment return uri else: return save(uri, top=False, base_url=base_url, relative_uris=relative_uris) def shortname(inputid: str) -> str: """ Compute the shortname of a fully qualified identifier. See https://w3id.org/cwl/v1.2/SchemaSalad.html#Short_names. """ parsed_id: Final = urlparse(inputid) if parsed_id.fragment: return parsed_id.fragment.split("/")[-1] return parsed_id.path.split("/")[-1] def parser_info() -> str: return "org.w3id.cwl.v1_1" class Documented(Saveable): pass class RecordField(Documented): """ A field of a record. """ name: str def __init__( self, name: Any, type_: Any, doc: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.doc = doc self.name = name if name is not None else "_:" + str(_uuid__.uuid4()) self.type_ = type_ def __eq__(self, other: Any) -> bool: if isinstance(other, RecordField): return bool( self.doc == other.doc and self.name == other.name and self.type_ == other.type_ ) return False def __hash__(self) -> int: return hash((self.doc, self.name, self.type_)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "RecordField": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] name = None if "name" in _doc: try: name = load_field( _doc.get("name"), uri_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("name") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `name`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("name") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [e], detailed_message=f"the `name` field with value `{val}` " "is not valid because:", ) ) __original_name_is_none = name is None if name is None: if docRoot is not None: name = docRoot else: _errors__.append(ValidationException("missing name")) if not __original_name_is_none: baseuri = cast(str, name) doc = None if "doc" in _doc: try: doc = load_field( _doc.get("doc"), union_of_None_type_or_strtype_or_array_of_strtype, baseuri, loadingOptions, lc=_doc.get("doc") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `doc`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("doc") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [e], detailed_message=f"the `doc` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("type") is None: raise ValidationException("missing required field `type`", None, []) type_ = load_field( _doc.get("type"), typedsl_union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype_or_array_of_union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype_2, baseuri, loadingOptions, lc=_doc.get("type") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `type`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("type") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [e], detailed_message=f"the `type` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `doc`, `name`, `type`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( doc=doc, name=name, type_=type_, extension_fields=extension_fields, loadingOptions=loadingOptions, ) loadingOptions.idx[cast(str, name)] = (_constructed, loadingOptions) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.name is not None: u = save_relative_uri(self.name, base_url, True, None, relative_uris) r["name"] = u if self.doc is not None: r["doc"] = save( self.doc, top=False, base_url=self.name, relative_uris=relative_uris ) if self.type_ is not None: r["type"] = save( self.type_, top=False, base_url=self.name, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["doc", "name", "type"]) class RecordSchema(Saveable): def __init__( self, type_: Any, fields: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.fields = fields self.type_ = type_ def __eq__(self, other: Any) -> bool: if isinstance(other, RecordSchema): return bool(self.fields == other.fields and self.type_ == other.type_) return False def __hash__(self) -> int: return hash((self.fields, self.type_)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "RecordSchema": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] fields = None if "fields" in _doc: try: fields = load_field( _doc.get("fields"), idmap_fields_union_of_None_type_or_array_of_RecordFieldLoader, baseuri, loadingOptions, lc=_doc.get("fields") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `fields`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("fields") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `fields` field is not valid because:", SourceLine(_doc, "fields", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `fields` field is not valid because:", SourceLine(_doc, "fields", str), [e], detailed_message=f"the `fields` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("type") is None: raise ValidationException("missing required field `type`", None, []) type_ = load_field( _doc.get("type"), typedsl_Record_nameLoader_2, baseuri, loadingOptions, lc=_doc.get("type") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `type`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("type") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [e], detailed_message=f"the `type` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `fields`, `type`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( fields=fields, type_=type_, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.fields is not None: r["fields"] = save( self.fields, top=False, base_url=base_url, relative_uris=relative_uris ) if self.type_ is not None: r["type"] = save( self.type_, top=False, base_url=base_url, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["fields", "type"]) class EnumSchema(Saveable): """ Define an enumerated type. """ name: str def __init__( self, symbols: Any, type_: Any, name: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.name = name if name is not None else "_:" + str(_uuid__.uuid4()) self.symbols = symbols self.type_ = type_ def __eq__(self, other: Any) -> bool: if isinstance(other, EnumSchema): return bool( self.name == other.name and self.symbols == other.symbols and self.type_ == other.type_ ) return False def __hash__(self) -> int: return hash((self.name, self.symbols, self.type_)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "EnumSchema": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] name = None if "name" in _doc: try: name = load_field( _doc.get("name"), uri_union_of_None_type_or_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("name") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `name`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("name") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [e], detailed_message=f"the `name` field with value `{val}` " "is not valid because:", ) ) __original_name_is_none = name is None if name is None: if docRoot is not None: name = docRoot else: name = "_:" + str(_uuid__.uuid4()) if not __original_name_is_none: baseuri = cast(str, name) try: if _doc.get("symbols") is None: raise ValidationException("missing required field `symbols`", None, []) symbols = load_field( _doc.get("symbols"), uri_array_of_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("symbols") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `symbols`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("symbols") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `symbols` field is not valid because:", SourceLine(_doc, "symbols", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `symbols` field is not valid because:", SourceLine(_doc, "symbols", str), [e], detailed_message=f"the `symbols` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("type") is None: raise ValidationException("missing required field `type`", None, []) type_ = load_field( _doc.get("type"), typedsl_Enum_nameLoader_2, baseuri, loadingOptions, lc=_doc.get("type") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `type`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("type") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [e], detailed_message=f"the `type` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `name`, `symbols`, `type`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( name=name, symbols=symbols, type_=type_, extension_fields=extension_fields, loadingOptions=loadingOptions, ) loadingOptions.idx[cast(str, name)] = (_constructed, loadingOptions) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.name is not None: u = save_relative_uri(self.name, base_url, True, None, relative_uris) r["name"] = u if self.symbols is not None: u = save_relative_uri(self.symbols, self.name, True, None, relative_uris) r["symbols"] = u if self.type_ is not None: r["type"] = save( self.type_, top=False, base_url=self.name, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["name", "symbols", "type"]) class ArraySchema(Saveable): def __init__( self, items: Any, type_: Any, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.items = items self.type_ = type_ def __eq__(self, other: Any) -> bool: if isinstance(other, ArraySchema): return bool(self.items == other.items and self.type_ == other.type_) return False def __hash__(self) -> int: return hash((self.items, self.type_)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "ArraySchema": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("items") is None: raise ValidationException("missing required field `items`", None, []) items = load_field( _doc.get("items"), uri_union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype_or_array_of_union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype_False_True_2_None, baseuri, loadingOptions, lc=_doc.get("items") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `items`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("items") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `items` field is not valid because:", SourceLine(_doc, "items", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `items` field is not valid because:", SourceLine(_doc, "items", str), [e], detailed_message=f"the `items` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("type") is None: raise ValidationException("missing required field `type`", None, []) type_ = load_field( _doc.get("type"), typedsl_Array_nameLoader_2, baseuri, loadingOptions, lc=_doc.get("type") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `type`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("type") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [e], detailed_message=f"the `type` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `items`, `type`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( items=items, type_=type_, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.items is not None: u = save_relative_uri(self.items, base_url, False, 2, relative_uris) r["items"] = u if self.type_ is not None: r["type"] = save( self.type_, top=False, base_url=base_url, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["items", "type"]) class MapSchema(Saveable): def __init__( self, type_: Any, values: Any, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.type_ = type_ self.values = values def __eq__(self, other: Any) -> bool: if isinstance(other, MapSchema): return bool(self.type_ == other.type_ and self.values == other.values) return False def __hash__(self) -> int: return hash((self.type_, self.values)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "MapSchema": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("type") is None: raise ValidationException("missing required field `type`", None, []) type_ = load_field( _doc.get("type"), typedsl_Map_nameLoader_2, baseuri, loadingOptions, lc=_doc.get("type") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `type`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("type") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [e], detailed_message=f"the `type` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("values") is None: raise ValidationException("missing required field `values`", None, []) values = load_field( _doc.get("values"), uri_union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype_or_array_of_union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype_False_True_2_None, baseuri, loadingOptions, lc=_doc.get("values") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `values`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("values") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `values` field is not valid because:", SourceLine(_doc, "values", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `values` field is not valid because:", SourceLine(_doc, "values", str), [e], detailed_message=f"the `values` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `type`, `values`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( type_=type_, values=values, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.type_ is not None: r["type"] = save( self.type_, top=False, base_url=base_url, relative_uris=relative_uris ) if self.values is not None: u = save_relative_uri(self.values, base_url, False, 2, relative_uris) r["values"] = u # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["type", "values"]) class UnionSchema(Saveable): def __init__( self, names: Any, type_: Any, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.names = names self.type_ = type_ def __eq__(self, other: Any) -> bool: if isinstance(other, UnionSchema): return bool(self.names == other.names and self.type_ == other.type_) return False def __hash__(self) -> int: return hash((self.names, self.type_)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "UnionSchema": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("names") is None: raise ValidationException("missing required field `names`", None, []) names = load_field( _doc.get("names"), uri_union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype_or_array_of_union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype_False_True_2_None, baseuri, loadingOptions, lc=_doc.get("names") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `names`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("names") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `names` field is not valid because:", SourceLine(_doc, "names", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `names` field is not valid because:", SourceLine(_doc, "names", str), [e], detailed_message=f"the `names` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("type") is None: raise ValidationException("missing required field `type`", None, []) type_ = load_field( _doc.get("type"), typedsl_Union_nameLoader_2, baseuri, loadingOptions, lc=_doc.get("type") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `type`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("type") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [e], detailed_message=f"the `type` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `names`, `type`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( names=names, type_=type_, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.names is not None: u = save_relative_uri(self.names, base_url, False, 2, relative_uris) r["names"] = u if self.type_ is not None: r["type"] = save( self.type_, top=False, base_url=base_url, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["names", "type"]) class CWLArraySchema(ArraySchema): def __init__( self, items: Any, type_: Any, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.items = items self.type_ = type_ def __eq__(self, other: Any) -> bool: if isinstance(other, CWLArraySchema): return bool(self.items == other.items and self.type_ == other.type_) return False def __hash__(self) -> int: return hash((self.items, self.type_)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "CWLArraySchema": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("items") is None: raise ValidationException("missing required field `items`", None, []) items = load_field( _doc.get("items"), uri_union_of_PrimitiveTypeLoader_or_CWLRecordSchemaLoader_or_EnumSchemaLoader_or_CWLArraySchemaLoader_or_strtype_or_array_of_union_of_PrimitiveTypeLoader_or_CWLRecordSchemaLoader_or_EnumSchemaLoader_or_CWLArraySchemaLoader_or_strtype_False_True_2_None, baseuri, loadingOptions, lc=_doc.get("items") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `items`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("items") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `items` field is not valid because:", SourceLine(_doc, "items", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `items` field is not valid because:", SourceLine(_doc, "items", str), [e], detailed_message=f"the `items` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("type") is None: raise ValidationException("missing required field `type`", None, []) type_ = load_field( _doc.get("type"), typedsl_Array_nameLoader_2, baseuri, loadingOptions, lc=_doc.get("type") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `type`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("type") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [e], detailed_message=f"the `type` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `items`, `type`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( items=items, type_=type_, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.items is not None: u = save_relative_uri(self.items, base_url, False, 2, relative_uris) r["items"] = u if self.type_ is not None: r["type"] = save( self.type_, top=False, base_url=base_url, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["items", "type"]) class CWLRecordField(RecordField): name: str def __init__( self, name: Any, type_: Any, doc: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.doc = doc self.name = name if name is not None else "_:" + str(_uuid__.uuid4()) self.type_ = type_ def __eq__(self, other: Any) -> bool: if isinstance(other, CWLRecordField): return bool( self.doc == other.doc and self.name == other.name and self.type_ == other.type_ ) return False def __hash__(self) -> int: return hash((self.doc, self.name, self.type_)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "CWLRecordField": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] name = None if "name" in _doc: try: name = load_field( _doc.get("name"), uri_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("name") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `name`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("name") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [e], detailed_message=f"the `name` field with value `{val}` " "is not valid because:", ) ) __original_name_is_none = name is None if name is None: if docRoot is not None: name = docRoot else: _errors__.append(ValidationException("missing name")) if not __original_name_is_none: baseuri = cast(str, name) doc = None if "doc" in _doc: try: doc = load_field( _doc.get("doc"), union_of_None_type_or_strtype_or_array_of_strtype, baseuri, loadingOptions, lc=_doc.get("doc") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `doc`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("doc") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [e], detailed_message=f"the `doc` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("type") is None: raise ValidationException("missing required field `type`", None, []) type_ = load_field( _doc.get("type"), typedsl_union_of_PrimitiveTypeLoader_or_CWLRecordSchemaLoader_or_EnumSchemaLoader_or_CWLArraySchemaLoader_or_strtype_or_array_of_union_of_PrimitiveTypeLoader_or_CWLRecordSchemaLoader_or_EnumSchemaLoader_or_CWLArraySchemaLoader_or_strtype_2, baseuri, loadingOptions, lc=_doc.get("type") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `type`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("type") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [e], detailed_message=f"the `type` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `doc`, `name`, `type`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( doc=doc, name=name, type_=type_, extension_fields=extension_fields, loadingOptions=loadingOptions, ) loadingOptions.idx[cast(str, name)] = (_constructed, loadingOptions) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.name is not None: u = save_relative_uri(self.name, base_url, True, None, relative_uris) r["name"] = u if self.doc is not None: r["doc"] = save( self.doc, top=False, base_url=self.name, relative_uris=relative_uris ) if self.type_ is not None: r["type"] = save( self.type_, top=False, base_url=self.name, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["doc", "name", "type"]) class CWLRecordSchema(RecordSchema): def __init__( self, type_: Any, fields: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.fields = fields self.type_ = type_ def __eq__(self, other: Any) -> bool: if isinstance(other, CWLRecordSchema): return bool(self.fields == other.fields and self.type_ == other.type_) return False def __hash__(self) -> int: return hash((self.fields, self.type_)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "CWLRecordSchema": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] fields = None if "fields" in _doc: try: fields = load_field( _doc.get("fields"), idmap_fields_union_of_None_type_or_array_of_CWLRecordFieldLoader, baseuri, loadingOptions, lc=_doc.get("fields") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `fields`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("fields") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `fields` field is not valid because:", SourceLine(_doc, "fields", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `fields` field is not valid because:", SourceLine(_doc, "fields", str), [e], detailed_message=f"the `fields` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("type") is None: raise ValidationException("missing required field `type`", None, []) type_ = load_field( _doc.get("type"), typedsl_Record_nameLoader_2, baseuri, loadingOptions, lc=_doc.get("type") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `type`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("type") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [e], detailed_message=f"the `type` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `fields`, `type`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( fields=fields, type_=type_, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.fields is not None: r["fields"] = save( self.fields, top=False, base_url=base_url, relative_uris=relative_uris ) if self.type_ is not None: r["type"] = save( self.type_, top=False, base_url=base_url, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["fields", "type"]) class File(Saveable): """ Represents a file (or group of files when `secondaryFiles` is provided) that will be accessible by tools using standard POSIX file system call API such as open(2) and read(2). Files are represented as objects with `class` of `File`. File objects have a number of properties that provide metadata about the file. The `location` property of a File is a URI that uniquely identifies the file. Implementations must support the file:// URI scheme and may support other schemes such as http://. The value of `location` may also be a relative reference, in which case it must be resolved relative to the URI of the document it appears in. Alternately to `location`, implementations must also accept the `path` property on File, which must be a filesystem path available on the same host as the CWL runner (for inputs) or the runtime environment of a command line tool execution (for command line tool outputs). If no `location` or `path` is specified, a file object must specify `contents` with the UTF-8 text content of the file. This is a "file literal". File literals do not correspond to external resources, but are created on disk with `contents` with when needed for a executing a tool. Where appropriate, expressions can return file literals to define new files on a runtime. The maximum size of `contents` is 64 kilobytes. The `basename` property defines the filename on disk where the file is staged. This may differ from the resource name. If not provided, `basename` must be computed from the last path part of `location` and made available to expressions. The `secondaryFiles` property is a list of File or Directory objects that must be staged in the same directory as the primary file. It is an error for file names to be duplicated in `secondaryFiles`. The `size` property is the size in bytes of the File. It must be computed from the resource and made available to expressions. The `checksum` field contains a cryptographic hash of the file content for use it verifying file contents. Implementations may, at user option, enable or disable computation of the `checksum` field for performance or other reasons. However, the ability to compute output checksums is required to pass the CWL conformance test suite. When executing a CommandLineTool, the files and secondary files may be staged to an arbitrary directory, but must use the value of `basename` for the filename. The `path` property must be file path in the context of the tool execution runtime (local to the compute node, or within the executing container). All computed properties should be available to expressions. File literals also must be staged and `path` must be set. When collecting CommandLineTool outputs, `glob` matching returns file paths (with the `path` property) and the derived properties. This can all be modified by `outputEval`. Alternately, if the file `cwl.output.json` is present in the output, `outputBinding` is ignored. File objects in the output must provide either a `location` URI or a `path` property in the context of the tool execution runtime (local to the compute node, or within the executing container). When evaluating an ExpressionTool, file objects must be referenced via `location` (the expression tool does not have access to files on disk so `path` is meaningless) or as file literals. It is legal to return a file object with an existing `location` but a different `basename`. The `loadContents` field of ExpressionTool inputs behaves the same as on CommandLineTool inputs, however it is not meaningful on the outputs. An ExpressionTool may forward file references from input to output by using the same value for `location`. """ def __init__( self, location: Optional[Any] = None, path: Optional[Any] = None, basename: Optional[Any] = None, dirname: Optional[Any] = None, nameroot: Optional[Any] = None, nameext: Optional[Any] = None, checksum: Optional[Any] = None, size: Optional[Any] = None, secondaryFiles: Optional[Any] = None, format: Optional[Any] = None, contents: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.class_ = "File" self.location = location self.path = path self.basename = basename self.dirname = dirname self.nameroot = nameroot self.nameext = nameext self.checksum = checksum self.size = size self.secondaryFiles = secondaryFiles self.format = format self.contents = contents def __eq__(self, other: Any) -> bool: if isinstance(other, File): return bool( self.class_ == other.class_ and self.location == other.location and self.path == other.path and self.basename == other.basename and self.dirname == other.dirname and self.nameroot == other.nameroot and self.nameext == other.nameext and self.checksum == other.checksum and self.size == other.size and self.secondaryFiles == other.secondaryFiles and self.format == other.format and self.contents == other.contents ) return False def __hash__(self) -> int: return hash( ( self.class_, self.location, self.path, self.basename, self.dirname, self.nameroot, self.nameext, self.checksum, self.size, self.secondaryFiles, self.format, self.contents, ) ) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "File": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("class") is None: raise ValidationException("missing required field `class`", None, []) class_ = load_field( _doc.get("class"), uri_File_classLoader_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("class") ) if class_ not in (cls.__name__, loadingOptions.vocab.get(cls.__name__)): raise ValidationException(f"tried `{cls.__name__}` but") except ValidationException as e: raise e location = None if "location" in _doc: try: location = load_field( _doc.get("location"), uri_union_of_None_type_or_strtype_False_False_None_None, baseuri, loadingOptions, lc=_doc.get("location") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `location`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("location") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `location` field is not valid because:", SourceLine(_doc, "location", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `location` field is not valid because:", SourceLine(_doc, "location", str), [e], detailed_message=f"the `location` field with value `{val}` " "is not valid because:", ) ) path = None if "path" in _doc: try: path = load_field( _doc.get("path"), uri_union_of_None_type_or_strtype_False_False_None_None, baseuri, loadingOptions, lc=_doc.get("path") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `path`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("path") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `path` field is not valid because:", SourceLine(_doc, "path", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `path` field is not valid because:", SourceLine(_doc, "path", str), [e], detailed_message=f"the `path` field with value `{val}` " "is not valid because:", ) ) basename = None if "basename" in _doc: try: basename = load_field( _doc.get("basename"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("basename") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `basename`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("basename") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `basename` field is not valid because:", SourceLine(_doc, "basename", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `basename` field is not valid because:", SourceLine(_doc, "basename", str), [e], detailed_message=f"the `basename` field with value `{val}` " "is not valid because:", ) ) dirname = None if "dirname" in _doc: try: dirname = load_field( _doc.get("dirname"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("dirname") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `dirname`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("dirname") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `dirname` field is not valid because:", SourceLine(_doc, "dirname", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `dirname` field is not valid because:", SourceLine(_doc, "dirname", str), [e], detailed_message=f"the `dirname` field with value `{val}` " "is not valid because:", ) ) nameroot = None if "nameroot" in _doc: try: nameroot = load_field( _doc.get("nameroot"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("nameroot") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `nameroot`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("nameroot") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `nameroot` field is not valid because:", SourceLine(_doc, "nameroot", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `nameroot` field is not valid because:", SourceLine(_doc, "nameroot", str), [e], detailed_message=f"the `nameroot` field with value `{val}` " "is not valid because:", ) ) nameext = None if "nameext" in _doc: try: nameext = load_field( _doc.get("nameext"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("nameext") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `nameext`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("nameext") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `nameext` field is not valid because:", SourceLine(_doc, "nameext", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `nameext` field is not valid because:", SourceLine(_doc, "nameext", str), [e], detailed_message=f"the `nameext` field with value `{val}` " "is not valid because:", ) ) checksum = None if "checksum" in _doc: try: checksum = load_field( _doc.get("checksum"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("checksum") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `checksum`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("checksum") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `checksum` field is not valid because:", SourceLine(_doc, "checksum", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `checksum` field is not valid because:", SourceLine(_doc, "checksum", str), [e], detailed_message=f"the `checksum` field with value `{val}` " "is not valid because:", ) ) size = None if "size" in _doc: try: size = load_field( _doc.get("size"), union_of_None_type_or_inttype, baseuri, loadingOptions, lc=_doc.get("size") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `size`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("size") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `size` field is not valid because:", SourceLine(_doc, "size", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `size` field is not valid because:", SourceLine(_doc, "size", str), [e], detailed_message=f"the `size` field with value `{val}` " "is not valid because:", ) ) secondaryFiles = None if "secondaryFiles" in _doc: try: secondaryFiles = load_field( _doc.get("secondaryFiles"), secondaryfilesdsl_union_of_None_type_or_array_of_union_of_FileLoader_or_DirectoryLoader, baseuri, loadingOptions, lc=_doc.get("secondaryFiles") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `secondaryFiles`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("secondaryFiles") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `secondaryFiles` field is not valid because:", SourceLine(_doc, "secondaryFiles", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `secondaryFiles` field is not valid because:", SourceLine(_doc, "secondaryFiles", str), [e], detailed_message=f"the `secondaryFiles` field with value `{val}` " "is not valid because:", ) ) format = None if "format" in _doc: try: format = load_field( _doc.get("format"), uri_union_of_None_type_or_strtype_True_False_None_True, baseuri, loadingOptions, lc=_doc.get("format") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `format`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("format") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `format` field is not valid because:", SourceLine(_doc, "format", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `format` field is not valid because:", SourceLine(_doc, "format", str), [e], detailed_message=f"the `format` field with value `{val}` " "is not valid because:", ) ) contents = None if "contents" in _doc: try: contents = load_field( _doc.get("contents"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("contents") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `contents`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("contents") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `contents` field is not valid because:", SourceLine(_doc, "contents", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `contents` field is not valid because:", SourceLine(_doc, "contents", str), [e], detailed_message=f"the `contents` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `class`, `location`, `path`, `basename`, `dirname`, `nameroot`, `nameext`, `checksum`, `size`, `secondaryFiles`, `format`, `contents`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( location=location, path=path, basename=basename, dirname=dirname, nameroot=nameroot, nameext=nameext, checksum=checksum, size=size, secondaryFiles=secondaryFiles, format=format, contents=contents, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.class_ is not None: uri = self.loadingOptions.vocab[self.class_] if p := self.loadingOptions.rvocab.get(uri[: -len(self.class_)]): uri = f"{p}:{self.class_}" else: uri = self.class_ u = save_relative_uri(uri, base_url, False, None, relative_uris) r["class"] = u if self.location is not None: u = save_relative_uri(self.location, base_url, False, None, relative_uris) r["location"] = u if self.path is not None: u = save_relative_uri(self.path, base_url, False, None, relative_uris) r["path"] = u if self.basename is not None: r["basename"] = save( self.basename, top=False, base_url=base_url, relative_uris=relative_uris ) if self.dirname is not None: r["dirname"] = save( self.dirname, top=False, base_url=base_url, relative_uris=relative_uris ) if self.nameroot is not None: r["nameroot"] = save( self.nameroot, top=False, base_url=base_url, relative_uris=relative_uris ) if self.nameext is not None: r["nameext"] = save( self.nameext, top=False, base_url=base_url, relative_uris=relative_uris ) if self.checksum is not None: r["checksum"] = save( self.checksum, top=False, base_url=base_url, relative_uris=relative_uris ) if self.size is not None: r["size"] = save( self.size, top=False, base_url=base_url, relative_uris=relative_uris ) if self.secondaryFiles is not None: r["secondaryFiles"] = save( self.secondaryFiles, top=False, base_url=base_url, relative_uris=relative_uris, ) if self.format is not None: u = save_relative_uri(self.format, base_url, True, None, relative_uris) r["format"] = u if self.contents is not None: r["contents"] = save( self.contents, top=False, base_url=base_url, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset( [ "class", "location", "path", "basename", "dirname", "nameroot", "nameext", "checksum", "size", "secondaryFiles", "format", "contents", ] ) class Directory(Saveable): """ Represents a directory to present to a command line tool. Directories are represented as objects with `class` of `Directory`. Directory objects have a number of properties that provide metadata about the directory. The `location` property of a Directory is a URI that uniquely identifies the directory. Implementations must support the file:// URI scheme and may support other schemes such as http://. Alternately to `location`, implementations must also accept the `path` property on Directory, which must be a filesystem path available on the same host as the CWL runner (for inputs) or the runtime environment of a command line tool execution (for command line tool outputs). A Directory object may have a `listing` field. This is a list of File and Directory objects that are contained in the Directory. For each entry in `listing`, the `basename` property defines the name of the File or Subdirectory when staged to disk. If `listing` is not provided, the implementation must have some way of fetching the Directory listing at runtime based on the `location` field. If a Directory does not have `location`, it is a Directory literal. A Directory literal must provide `listing`. Directory literals must be created on disk at runtime as needed. The resources in a Directory literal do not need to have any implied relationship in their `location`. For example, a Directory listing may contain two files located on different hosts. It is the responsibility of the runtime to ensure that those files are staged to disk appropriately. Secondary files associated with files in `listing` must also be staged to the same Directory. When executing a CommandLineTool, Directories must be recursively staged first and have local values of `path` assigend. Directory objects in CommandLineTool output must provide either a `location` URI or a `path` property in the context of the tool execution runtime (local to the compute node, or within the executing container). An ExpressionTool may forward file references from input to output by using the same value for `location`. Name conflicts (the same `basename` appearing multiple times in `listing` or in any entry in `secondaryFiles` in the listing) is a fatal error. """ def __init__( self, location: Optional[Any] = None, path: Optional[Any] = None, basename: Optional[Any] = None, listing: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.class_ = "Directory" self.location = location self.path = path self.basename = basename self.listing = listing def __eq__(self, other: Any) -> bool: if isinstance(other, Directory): return bool( self.class_ == other.class_ and self.location == other.location and self.path == other.path and self.basename == other.basename and self.listing == other.listing ) return False def __hash__(self) -> int: return hash( (self.class_, self.location, self.path, self.basename, self.listing) ) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "Directory": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("class") is None: raise ValidationException("missing required field `class`", None, []) class_ = load_field( _doc.get("class"), uri_Directory_classLoader_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("class") ) if class_ not in (cls.__name__, loadingOptions.vocab.get(cls.__name__)): raise ValidationException(f"tried `{cls.__name__}` but") except ValidationException as e: raise e location = None if "location" in _doc: try: location = load_field( _doc.get("location"), uri_union_of_None_type_or_strtype_False_False_None_None, baseuri, loadingOptions, lc=_doc.get("location") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `location`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("location") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `location` field is not valid because:", SourceLine(_doc, "location", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `location` field is not valid because:", SourceLine(_doc, "location", str), [e], detailed_message=f"the `location` field with value `{val}` " "is not valid because:", ) ) path = None if "path" in _doc: try: path = load_field( _doc.get("path"), uri_union_of_None_type_or_strtype_False_False_None_None, baseuri, loadingOptions, lc=_doc.get("path") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `path`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("path") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `path` field is not valid because:", SourceLine(_doc, "path", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `path` field is not valid because:", SourceLine(_doc, "path", str), [e], detailed_message=f"the `path` field with value `{val}` " "is not valid because:", ) ) basename = None if "basename" in _doc: try: basename = load_field( _doc.get("basename"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("basename") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `basename`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("basename") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `basename` field is not valid because:", SourceLine(_doc, "basename", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `basename` field is not valid because:", SourceLine(_doc, "basename", str), [e], detailed_message=f"the `basename` field with value `{val}` " "is not valid because:", ) ) listing = None if "listing" in _doc: try: listing = load_field( _doc.get("listing"), union_of_None_type_or_array_of_union_of_FileLoader_or_DirectoryLoader, baseuri, loadingOptions, lc=_doc.get("listing") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `listing`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("listing") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `listing` field is not valid because:", SourceLine(_doc, "listing", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `listing` field is not valid because:", SourceLine(_doc, "listing", str), [e], detailed_message=f"the `listing` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `class`, `location`, `path`, `basename`, `listing`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( location=location, path=path, basename=basename, listing=listing, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.class_ is not None: uri = self.loadingOptions.vocab[self.class_] if p := self.loadingOptions.rvocab.get(uri[: -len(self.class_)]): uri = f"{p}:{self.class_}" else: uri = self.class_ u = save_relative_uri(uri, base_url, False, None, relative_uris) r["class"] = u if self.location is not None: u = save_relative_uri(self.location, base_url, False, None, relative_uris) r["location"] = u if self.path is not None: u = save_relative_uri(self.path, base_url, False, None, relative_uris) r["path"] = u if self.basename is not None: r["basename"] = save( self.basename, top=False, base_url=base_url, relative_uris=relative_uris ) if self.listing is not None: r["listing"] = save( self.listing, top=False, base_url=base_url, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["class", "location", "path", "basename", "listing"]) class Labeled(Saveable): pass class Identified(Saveable): pass class IdentifierRequired(Identified): pass class LoadContents(Saveable): pass class FieldBase(Labeled): pass class InputFormat(Saveable): pass class OutputFormat(Saveable): pass class Parameter(FieldBase, Documented, IdentifierRequired): """ Define an input or output parameter to a process. """ pass class InputBinding(Saveable): def __init__( self, loadContents: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.loadContents = loadContents def __eq__(self, other: Any) -> bool: if isinstance(other, InputBinding): return bool(self.loadContents == other.loadContents) return False def __hash__(self) -> int: return hash((self.loadContents)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "InputBinding": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] loadContents = None if "loadContents" in _doc: try: loadContents = load_field( _doc.get("loadContents"), union_of_None_type_or_booltype, baseuri, loadingOptions, lc=_doc.get("loadContents") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `loadContents`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("loadContents") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `loadContents` field is not valid because:", SourceLine(_doc, "loadContents", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `loadContents` field is not valid because:", SourceLine(_doc, "loadContents", str), [e], detailed_message=f"the `loadContents` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `loadContents`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( loadContents=loadContents, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.loadContents is not None: r["loadContents"] = save( self.loadContents, top=False, base_url=base_url, relative_uris=relative_uris, ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["loadContents"]) class IOSchema(Labeled, Documented): pass class InputSchema(IOSchema): pass class OutputSchema(IOSchema): pass class InputRecordField(CWLRecordField, FieldBase, InputFormat, LoadContents): name: str def __init__( self, name: Any, type_: Any, doc: Optional[Any] = None, label: Optional[Any] = None, secondaryFiles: Optional[Any] = None, streamable: Optional[Any] = None, format: Optional[Any] = None, loadContents: Optional[Any] = None, loadListing: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.doc = doc self.name = name if name is not None else "_:" + str(_uuid__.uuid4()) self.type_ = type_ self.label = label self.secondaryFiles = secondaryFiles self.streamable = streamable self.format = format self.loadContents = loadContents self.loadListing = loadListing def __eq__(self, other: Any) -> bool: if isinstance(other, InputRecordField): return bool( self.doc == other.doc and self.name == other.name and self.type_ == other.type_ and self.label == other.label and self.secondaryFiles == other.secondaryFiles and self.streamable == other.streamable and self.format == other.format and self.loadContents == other.loadContents and self.loadListing == other.loadListing ) return False def __hash__(self) -> int: return hash( ( self.doc, self.name, self.type_, self.label, self.secondaryFiles, self.streamable, self.format, self.loadContents, self.loadListing, ) ) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "InputRecordField": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] name = None if "name" in _doc: try: name = load_field( _doc.get("name"), uri_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("name") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `name`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("name") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [e], detailed_message=f"the `name` field with value `{val}` " "is not valid because:", ) ) __original_name_is_none = name is None if name is None: if docRoot is not None: name = docRoot else: _errors__.append(ValidationException("missing name")) if not __original_name_is_none: baseuri = cast(str, name) doc = None if "doc" in _doc: try: doc = load_field( _doc.get("doc"), union_of_None_type_or_strtype_or_array_of_strtype, baseuri, loadingOptions, lc=_doc.get("doc") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `doc`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("doc") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [e], detailed_message=f"the `doc` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("type") is None: raise ValidationException("missing required field `type`", None, []) type_ = load_field( _doc.get("type"), typedsl_union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype_2, baseuri, loadingOptions, lc=_doc.get("type") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `type`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("type") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [e], detailed_message=f"the `type` field with value `{val}` " "is not valid because:", ) ) label = None if "label" in _doc: try: label = load_field( _doc.get("label"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("label") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `label`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("label") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [e], detailed_message=f"the `label` field with value `{val}` " "is not valid because:", ) ) secondaryFiles = None if "secondaryFiles" in _doc: try: secondaryFiles = load_field( _doc.get("secondaryFiles"), secondaryfilesdsl_union_of_None_type_or_SecondaryFileSchemaLoader_or_array_of_SecondaryFileSchemaLoader, baseuri, loadingOptions, lc=_doc.get("secondaryFiles") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `secondaryFiles`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("secondaryFiles") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `secondaryFiles` field is not valid because:", SourceLine(_doc, "secondaryFiles", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `secondaryFiles` field is not valid because:", SourceLine(_doc, "secondaryFiles", str), [e], detailed_message=f"the `secondaryFiles` field with value `{val}` " "is not valid because:", ) ) streamable = None if "streamable" in _doc: try: streamable = load_field( _doc.get("streamable"), union_of_None_type_or_booltype, baseuri, loadingOptions, lc=_doc.get("streamable") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `streamable`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("streamable") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `streamable` field is not valid because:", SourceLine(_doc, "streamable", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `streamable` field is not valid because:", SourceLine(_doc, "streamable", str), [e], detailed_message=f"the `streamable` field with value `{val}` " "is not valid because:", ) ) format = None if "format" in _doc: try: format = load_field( _doc.get("format"), uri_union_of_None_type_or_strtype_or_array_of_strtype_or_ExpressionLoader_True_False_None_True, baseuri, loadingOptions, lc=_doc.get("format") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `format`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("format") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `format` field is not valid because:", SourceLine(_doc, "format", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `format` field is not valid because:", SourceLine(_doc, "format", str), [e], detailed_message=f"the `format` field with value `{val}` " "is not valid because:", ) ) loadContents = None if "loadContents" in _doc: try: loadContents = load_field( _doc.get("loadContents"), union_of_None_type_or_booltype, baseuri, loadingOptions, lc=_doc.get("loadContents") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `loadContents`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("loadContents") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `loadContents` field is not valid because:", SourceLine(_doc, "loadContents", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `loadContents` field is not valid because:", SourceLine(_doc, "loadContents", str), [e], detailed_message=f"the `loadContents` field with value `{val}` " "is not valid because:", ) ) loadListing = None if "loadListing" in _doc: try: loadListing = load_field( _doc.get("loadListing"), union_of_None_type_or_LoadListingEnumLoader, baseuri, loadingOptions, lc=_doc.get("loadListing") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `loadListing`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("loadListing") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `loadListing` field is not valid because:", SourceLine(_doc, "loadListing", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `loadListing` field is not valid because:", SourceLine(_doc, "loadListing", str), [e], detailed_message=f"the `loadListing` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `doc`, `name`, `type`, `label`, `secondaryFiles`, `streamable`, `format`, `loadContents`, `loadListing`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( doc=doc, name=name, type_=type_, label=label, secondaryFiles=secondaryFiles, streamable=streamable, format=format, loadContents=loadContents, loadListing=loadListing, extension_fields=extension_fields, loadingOptions=loadingOptions, ) loadingOptions.idx[cast(str, name)] = (_constructed, loadingOptions) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.name is not None: u = save_relative_uri(self.name, base_url, True, None, relative_uris) r["name"] = u if self.doc is not None: r["doc"] = save( self.doc, top=False, base_url=self.name, relative_uris=relative_uris ) if self.type_ is not None: r["type"] = save( self.type_, top=False, base_url=self.name, relative_uris=relative_uris ) if self.label is not None: r["label"] = save( self.label, top=False, base_url=self.name, relative_uris=relative_uris ) if self.secondaryFiles is not None: r["secondaryFiles"] = save( self.secondaryFiles, top=False, base_url=self.name, relative_uris=relative_uris, ) if self.streamable is not None: r["streamable"] = save( self.streamable, top=False, base_url=self.name, relative_uris=relative_uris, ) if self.format is not None: u = save_relative_uri(self.format, self.name, True, None, relative_uris) r["format"] = u if self.loadContents is not None: r["loadContents"] = save( self.loadContents, top=False, base_url=self.name, relative_uris=relative_uris, ) if self.loadListing is not None: r["loadListing"] = save( self.loadListing, top=False, base_url=self.name, relative_uris=relative_uris, ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset( [ "doc", "name", "type", "label", "secondaryFiles", "streamable", "format", "loadContents", "loadListing", ] ) class InputRecordSchema(CWLRecordSchema, InputSchema): name: str def __init__( self, type_: Any, fields: Optional[Any] = None, label: Optional[Any] = None, doc: Optional[Any] = None, name: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.fields = fields self.type_ = type_ self.label = label self.doc = doc self.name = name if name is not None else "_:" + str(_uuid__.uuid4()) def __eq__(self, other: Any) -> bool: if isinstance(other, InputRecordSchema): return bool( self.fields == other.fields and self.type_ == other.type_ and self.label == other.label and self.doc == other.doc and self.name == other.name ) return False def __hash__(self) -> int: return hash((self.fields, self.type_, self.label, self.doc, self.name)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "InputRecordSchema": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] name = None if "name" in _doc: try: name = load_field( _doc.get("name"), uri_union_of_None_type_or_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("name") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `name`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("name") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [e], detailed_message=f"the `name` field with value `{val}` " "is not valid because:", ) ) __original_name_is_none = name is None if name is None: if docRoot is not None: name = docRoot else: name = "_:" + str(_uuid__.uuid4()) if not __original_name_is_none: baseuri = cast(str, name) fields = None if "fields" in _doc: try: fields = load_field( _doc.get("fields"), idmap_fields_union_of_None_type_or_array_of_InputRecordFieldLoader, baseuri, loadingOptions, lc=_doc.get("fields") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `fields`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("fields") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `fields` field is not valid because:", SourceLine(_doc, "fields", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `fields` field is not valid because:", SourceLine(_doc, "fields", str), [e], detailed_message=f"the `fields` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("type") is None: raise ValidationException("missing required field `type`", None, []) type_ = load_field( _doc.get("type"), typedsl_Record_nameLoader_2, baseuri, loadingOptions, lc=_doc.get("type") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `type`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("type") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [e], detailed_message=f"the `type` field with value `{val}` " "is not valid because:", ) ) label = None if "label" in _doc: try: label = load_field( _doc.get("label"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("label") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `label`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("label") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [e], detailed_message=f"the `label` field with value `{val}` " "is not valid because:", ) ) doc = None if "doc" in _doc: try: doc = load_field( _doc.get("doc"), union_of_None_type_or_strtype_or_array_of_strtype, baseuri, loadingOptions, lc=_doc.get("doc") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `doc`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("doc") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [e], detailed_message=f"the `doc` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `fields`, `type`, `label`, `doc`, `name`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( fields=fields, type_=type_, label=label, doc=doc, name=name, extension_fields=extension_fields, loadingOptions=loadingOptions, ) loadingOptions.idx[cast(str, name)] = (_constructed, loadingOptions) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.name is not None: u = save_relative_uri(self.name, base_url, True, None, relative_uris) r["name"] = u if self.fields is not None: r["fields"] = save( self.fields, top=False, base_url=self.name, relative_uris=relative_uris ) if self.type_ is not None: r["type"] = save( self.type_, top=False, base_url=self.name, relative_uris=relative_uris ) if self.label is not None: r["label"] = save( self.label, top=False, base_url=self.name, relative_uris=relative_uris ) if self.doc is not None: r["doc"] = save( self.doc, top=False, base_url=self.name, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["fields", "type", "label", "doc", "name"]) class InputEnumSchema(EnumSchema, InputSchema): name: str def __init__( self, symbols: Any, type_: Any, name: Optional[Any] = None, label: Optional[Any] = None, doc: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.name = name if name is not None else "_:" + str(_uuid__.uuid4()) self.symbols = symbols self.type_ = type_ self.label = label self.doc = doc def __eq__(self, other: Any) -> bool: if isinstance(other, InputEnumSchema): return bool( self.name == other.name and self.symbols == other.symbols and self.type_ == other.type_ and self.label == other.label and self.doc == other.doc ) return False def __hash__(self) -> int: return hash((self.name, self.symbols, self.type_, self.label, self.doc)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "InputEnumSchema": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] name = None if "name" in _doc: try: name = load_field( _doc.get("name"), uri_union_of_None_type_or_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("name") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `name`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("name") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [e], detailed_message=f"the `name` field with value `{val}` " "is not valid because:", ) ) __original_name_is_none = name is None if name is None: if docRoot is not None: name = docRoot else: name = "_:" + str(_uuid__.uuid4()) if not __original_name_is_none: baseuri = cast(str, name) try: if _doc.get("symbols") is None: raise ValidationException("missing required field `symbols`", None, []) symbols = load_field( _doc.get("symbols"), uri_array_of_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("symbols") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `symbols`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("symbols") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `symbols` field is not valid because:", SourceLine(_doc, "symbols", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `symbols` field is not valid because:", SourceLine(_doc, "symbols", str), [e], detailed_message=f"the `symbols` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("type") is None: raise ValidationException("missing required field `type`", None, []) type_ = load_field( _doc.get("type"), typedsl_Enum_nameLoader_2, baseuri, loadingOptions, lc=_doc.get("type") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `type`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("type") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [e], detailed_message=f"the `type` field with value `{val}` " "is not valid because:", ) ) label = None if "label" in _doc: try: label = load_field( _doc.get("label"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("label") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `label`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("label") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [e], detailed_message=f"the `label` field with value `{val}` " "is not valid because:", ) ) doc = None if "doc" in _doc: try: doc = load_field( _doc.get("doc"), union_of_None_type_or_strtype_or_array_of_strtype, baseuri, loadingOptions, lc=_doc.get("doc") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `doc`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("doc") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [e], detailed_message=f"the `doc` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `name`, `symbols`, `type`, `label`, `doc`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( name=name, symbols=symbols, type_=type_, label=label, doc=doc, extension_fields=extension_fields, loadingOptions=loadingOptions, ) loadingOptions.idx[cast(str, name)] = (_constructed, loadingOptions) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.name is not None: u = save_relative_uri(self.name, base_url, True, None, relative_uris) r["name"] = u if self.symbols is not None: u = save_relative_uri(self.symbols, self.name, True, None, relative_uris) r["symbols"] = u if self.type_ is not None: r["type"] = save( self.type_, top=False, base_url=self.name, relative_uris=relative_uris ) if self.label is not None: r["label"] = save( self.label, top=False, base_url=self.name, relative_uris=relative_uris ) if self.doc is not None: r["doc"] = save( self.doc, top=False, base_url=self.name, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["name", "symbols", "type", "label", "doc"]) class InputArraySchema(CWLArraySchema, InputSchema): name: str def __init__( self, items: Any, type_: Any, label: Optional[Any] = None, doc: Optional[Any] = None, name: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.items = items self.type_ = type_ self.label = label self.doc = doc self.name = name if name is not None else "_:" + str(_uuid__.uuid4()) def __eq__(self, other: Any) -> bool: if isinstance(other, InputArraySchema): return bool( self.items == other.items and self.type_ == other.type_ and self.label == other.label and self.doc == other.doc and self.name == other.name ) return False def __hash__(self) -> int: return hash((self.items, self.type_, self.label, self.doc, self.name)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "InputArraySchema": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] name = None if "name" in _doc: try: name = load_field( _doc.get("name"), uri_union_of_None_type_or_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("name") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `name`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("name") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [e], detailed_message=f"the `name` field with value `{val}` " "is not valid because:", ) ) __original_name_is_none = name is None if name is None: if docRoot is not None: name = docRoot else: name = "_:" + str(_uuid__.uuid4()) if not __original_name_is_none: baseuri = cast(str, name) try: if _doc.get("items") is None: raise ValidationException("missing required field `items`", None, []) items = load_field( _doc.get("items"), uri_union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype_False_True_2_None, baseuri, loadingOptions, lc=_doc.get("items") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `items`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("items") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `items` field is not valid because:", SourceLine(_doc, "items", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `items` field is not valid because:", SourceLine(_doc, "items", str), [e], detailed_message=f"the `items` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("type") is None: raise ValidationException("missing required field `type`", None, []) type_ = load_field( _doc.get("type"), typedsl_Array_nameLoader_2, baseuri, loadingOptions, lc=_doc.get("type") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `type`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("type") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [e], detailed_message=f"the `type` field with value `{val}` " "is not valid because:", ) ) label = None if "label" in _doc: try: label = load_field( _doc.get("label"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("label") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `label`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("label") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [e], detailed_message=f"the `label` field with value `{val}` " "is not valid because:", ) ) doc = None if "doc" in _doc: try: doc = load_field( _doc.get("doc"), union_of_None_type_or_strtype_or_array_of_strtype, baseuri, loadingOptions, lc=_doc.get("doc") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `doc`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("doc") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [e], detailed_message=f"the `doc` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `items`, `type`, `label`, `doc`, `name`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( items=items, type_=type_, label=label, doc=doc, name=name, extension_fields=extension_fields, loadingOptions=loadingOptions, ) loadingOptions.idx[cast(str, name)] = (_constructed, loadingOptions) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.name is not None: u = save_relative_uri(self.name, base_url, True, None, relative_uris) r["name"] = u if self.items is not None: u = save_relative_uri(self.items, self.name, False, 2, relative_uris) r["items"] = u if self.type_ is not None: r["type"] = save( self.type_, top=False, base_url=self.name, relative_uris=relative_uris ) if self.label is not None: r["label"] = save( self.label, top=False, base_url=self.name, relative_uris=relative_uris ) if self.doc is not None: r["doc"] = save( self.doc, top=False, base_url=self.name, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["items", "type", "label", "doc", "name"]) class OutputRecordField(CWLRecordField, FieldBase, OutputFormat): name: str def __init__( self, name: Any, type_: Any, doc: Optional[Any] = None, label: Optional[Any] = None, secondaryFiles: Optional[Any] = None, streamable: Optional[Any] = None, format: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.doc = doc self.name = name if name is not None else "_:" + str(_uuid__.uuid4()) self.type_ = type_ self.label = label self.secondaryFiles = secondaryFiles self.streamable = streamable self.format = format def __eq__(self, other: Any) -> bool: if isinstance(other, OutputRecordField): return bool( self.doc == other.doc and self.name == other.name and self.type_ == other.type_ and self.label == other.label and self.secondaryFiles == other.secondaryFiles and self.streamable == other.streamable and self.format == other.format ) return False def __hash__(self) -> int: return hash( ( self.doc, self.name, self.type_, self.label, self.secondaryFiles, self.streamable, self.format, ) ) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "OutputRecordField": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] name = None if "name" in _doc: try: name = load_field( _doc.get("name"), uri_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("name") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `name`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("name") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [e], detailed_message=f"the `name` field with value `{val}` " "is not valid because:", ) ) __original_name_is_none = name is None if name is None: if docRoot is not None: name = docRoot else: _errors__.append(ValidationException("missing name")) if not __original_name_is_none: baseuri = cast(str, name) doc = None if "doc" in _doc: try: doc = load_field( _doc.get("doc"), union_of_None_type_or_strtype_or_array_of_strtype, baseuri, loadingOptions, lc=_doc.get("doc") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `doc`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("doc") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [e], detailed_message=f"the `doc` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("type") is None: raise ValidationException("missing required field `type`", None, []) type_ = load_field( _doc.get("type"), typedsl_union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype_2, baseuri, loadingOptions, lc=_doc.get("type") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `type`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("type") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [e], detailed_message=f"the `type` field with value `{val}` " "is not valid because:", ) ) label = None if "label" in _doc: try: label = load_field( _doc.get("label"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("label") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `label`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("label") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [e], detailed_message=f"the `label` field with value `{val}` " "is not valid because:", ) ) secondaryFiles = None if "secondaryFiles" in _doc: try: secondaryFiles = load_field( _doc.get("secondaryFiles"), secondaryfilesdsl_union_of_None_type_or_SecondaryFileSchemaLoader_or_array_of_SecondaryFileSchemaLoader, baseuri, loadingOptions, lc=_doc.get("secondaryFiles") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `secondaryFiles`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("secondaryFiles") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `secondaryFiles` field is not valid because:", SourceLine(_doc, "secondaryFiles", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `secondaryFiles` field is not valid because:", SourceLine(_doc, "secondaryFiles", str), [e], detailed_message=f"the `secondaryFiles` field with value `{val}` " "is not valid because:", ) ) streamable = None if "streamable" in _doc: try: streamable = load_field( _doc.get("streamable"), union_of_None_type_or_booltype, baseuri, loadingOptions, lc=_doc.get("streamable") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `streamable`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("streamable") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `streamable` field is not valid because:", SourceLine(_doc, "streamable", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `streamable` field is not valid because:", SourceLine(_doc, "streamable", str), [e], detailed_message=f"the `streamable` field with value `{val}` " "is not valid because:", ) ) format = None if "format" in _doc: try: format = load_field( _doc.get("format"), uri_union_of_None_type_or_strtype_or_ExpressionLoader_True_False_None_True, baseuri, loadingOptions, lc=_doc.get("format") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `format`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("format") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `format` field is not valid because:", SourceLine(_doc, "format", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `format` field is not valid because:", SourceLine(_doc, "format", str), [e], detailed_message=f"the `format` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `doc`, `name`, `type`, `label`, `secondaryFiles`, `streamable`, `format`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( doc=doc, name=name, type_=type_, label=label, secondaryFiles=secondaryFiles, streamable=streamable, format=format, extension_fields=extension_fields, loadingOptions=loadingOptions, ) loadingOptions.idx[cast(str, name)] = (_constructed, loadingOptions) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.name is not None: u = save_relative_uri(self.name, base_url, True, None, relative_uris) r["name"] = u if self.doc is not None: r["doc"] = save( self.doc, top=False, base_url=self.name, relative_uris=relative_uris ) if self.type_ is not None: r["type"] = save( self.type_, top=False, base_url=self.name, relative_uris=relative_uris ) if self.label is not None: r["label"] = save( self.label, top=False, base_url=self.name, relative_uris=relative_uris ) if self.secondaryFiles is not None: r["secondaryFiles"] = save( self.secondaryFiles, top=False, base_url=self.name, relative_uris=relative_uris, ) if self.streamable is not None: r["streamable"] = save( self.streamable, top=False, base_url=self.name, relative_uris=relative_uris, ) if self.format is not None: u = save_relative_uri(self.format, self.name, True, None, relative_uris) r["format"] = u # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset( ["doc", "name", "type", "label", "secondaryFiles", "streamable", "format"] ) class OutputRecordSchema(CWLRecordSchema, OutputSchema): name: str def __init__( self, type_: Any, fields: Optional[Any] = None, label: Optional[Any] = None, doc: Optional[Any] = None, name: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.fields = fields self.type_ = type_ self.label = label self.doc = doc self.name = name if name is not None else "_:" + str(_uuid__.uuid4()) def __eq__(self, other: Any) -> bool: if isinstance(other, OutputRecordSchema): return bool( self.fields == other.fields and self.type_ == other.type_ and self.label == other.label and self.doc == other.doc and self.name == other.name ) return False def __hash__(self) -> int: return hash((self.fields, self.type_, self.label, self.doc, self.name)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "OutputRecordSchema": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] name = None if "name" in _doc: try: name = load_field( _doc.get("name"), uri_union_of_None_type_or_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("name") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `name`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("name") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [e], detailed_message=f"the `name` field with value `{val}` " "is not valid because:", ) ) __original_name_is_none = name is None if name is None: if docRoot is not None: name = docRoot else: name = "_:" + str(_uuid__.uuid4()) if not __original_name_is_none: baseuri = cast(str, name) fields = None if "fields" in _doc: try: fields = load_field( _doc.get("fields"), idmap_fields_union_of_None_type_or_array_of_OutputRecordFieldLoader, baseuri, loadingOptions, lc=_doc.get("fields") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `fields`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("fields") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `fields` field is not valid because:", SourceLine(_doc, "fields", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `fields` field is not valid because:", SourceLine(_doc, "fields", str), [e], detailed_message=f"the `fields` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("type") is None: raise ValidationException("missing required field `type`", None, []) type_ = load_field( _doc.get("type"), typedsl_Record_nameLoader_2, baseuri, loadingOptions, lc=_doc.get("type") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `type`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("type") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [e], detailed_message=f"the `type` field with value `{val}` " "is not valid because:", ) ) label = None if "label" in _doc: try: label = load_field( _doc.get("label"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("label") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `label`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("label") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [e], detailed_message=f"the `label` field with value `{val}` " "is not valid because:", ) ) doc = None if "doc" in _doc: try: doc = load_field( _doc.get("doc"), union_of_None_type_or_strtype_or_array_of_strtype, baseuri, loadingOptions, lc=_doc.get("doc") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `doc`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("doc") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [e], detailed_message=f"the `doc` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `fields`, `type`, `label`, `doc`, `name`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( fields=fields, type_=type_, label=label, doc=doc, name=name, extension_fields=extension_fields, loadingOptions=loadingOptions, ) loadingOptions.idx[cast(str, name)] = (_constructed, loadingOptions) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.name is not None: u = save_relative_uri(self.name, base_url, True, None, relative_uris) r["name"] = u if self.fields is not None: r["fields"] = save( self.fields, top=False, base_url=self.name, relative_uris=relative_uris ) if self.type_ is not None: r["type"] = save( self.type_, top=False, base_url=self.name, relative_uris=relative_uris ) if self.label is not None: r["label"] = save( self.label, top=False, base_url=self.name, relative_uris=relative_uris ) if self.doc is not None: r["doc"] = save( self.doc, top=False, base_url=self.name, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["fields", "type", "label", "doc", "name"]) class OutputEnumSchema(EnumSchema, OutputSchema): name: str def __init__( self, symbols: Any, type_: Any, name: Optional[Any] = None, label: Optional[Any] = None, doc: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.name = name if name is not None else "_:" + str(_uuid__.uuid4()) self.symbols = symbols self.type_ = type_ self.label = label self.doc = doc def __eq__(self, other: Any) -> bool: if isinstance(other, OutputEnumSchema): return bool( self.name == other.name and self.symbols == other.symbols and self.type_ == other.type_ and self.label == other.label and self.doc == other.doc ) return False def __hash__(self) -> int: return hash((self.name, self.symbols, self.type_, self.label, self.doc)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "OutputEnumSchema": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] name = None if "name" in _doc: try: name = load_field( _doc.get("name"), uri_union_of_None_type_or_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("name") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `name`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("name") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [e], detailed_message=f"the `name` field with value `{val}` " "is not valid because:", ) ) __original_name_is_none = name is None if name is None: if docRoot is not None: name = docRoot else: name = "_:" + str(_uuid__.uuid4()) if not __original_name_is_none: baseuri = cast(str, name) try: if _doc.get("symbols") is None: raise ValidationException("missing required field `symbols`", None, []) symbols = load_field( _doc.get("symbols"), uri_array_of_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("symbols") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `symbols`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("symbols") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `symbols` field is not valid because:", SourceLine(_doc, "symbols", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `symbols` field is not valid because:", SourceLine(_doc, "symbols", str), [e], detailed_message=f"the `symbols` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("type") is None: raise ValidationException("missing required field `type`", None, []) type_ = load_field( _doc.get("type"), typedsl_Enum_nameLoader_2, baseuri, loadingOptions, lc=_doc.get("type") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `type`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("type") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [e], detailed_message=f"the `type` field with value `{val}` " "is not valid because:", ) ) label = None if "label" in _doc: try: label = load_field( _doc.get("label"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("label") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `label`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("label") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [e], detailed_message=f"the `label` field with value `{val}` " "is not valid because:", ) ) doc = None if "doc" in _doc: try: doc = load_field( _doc.get("doc"), union_of_None_type_or_strtype_or_array_of_strtype, baseuri, loadingOptions, lc=_doc.get("doc") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `doc`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("doc") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [e], detailed_message=f"the `doc` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `name`, `symbols`, `type`, `label`, `doc`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( name=name, symbols=symbols, type_=type_, label=label, doc=doc, extension_fields=extension_fields, loadingOptions=loadingOptions, ) loadingOptions.idx[cast(str, name)] = (_constructed, loadingOptions) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.name is not None: u = save_relative_uri(self.name, base_url, True, None, relative_uris) r["name"] = u if self.symbols is not None: u = save_relative_uri(self.symbols, self.name, True, None, relative_uris) r["symbols"] = u if self.type_ is not None: r["type"] = save( self.type_, top=False, base_url=self.name, relative_uris=relative_uris ) if self.label is not None: r["label"] = save( self.label, top=False, base_url=self.name, relative_uris=relative_uris ) if self.doc is not None: r["doc"] = save( self.doc, top=False, base_url=self.name, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["name", "symbols", "type", "label", "doc"]) class OutputArraySchema(CWLArraySchema, OutputSchema): name: str def __init__( self, items: Any, type_: Any, label: Optional[Any] = None, doc: Optional[Any] = None, name: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.items = items self.type_ = type_ self.label = label self.doc = doc self.name = name if name is not None else "_:" + str(_uuid__.uuid4()) def __eq__(self, other: Any) -> bool: if isinstance(other, OutputArraySchema): return bool( self.items == other.items and self.type_ == other.type_ and self.label == other.label and self.doc == other.doc and self.name == other.name ) return False def __hash__(self) -> int: return hash((self.items, self.type_, self.label, self.doc, self.name)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "OutputArraySchema": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] name = None if "name" in _doc: try: name = load_field( _doc.get("name"), uri_union_of_None_type_or_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("name") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `name`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("name") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [e], detailed_message=f"the `name` field with value `{val}` " "is not valid because:", ) ) __original_name_is_none = name is None if name is None: if docRoot is not None: name = docRoot else: name = "_:" + str(_uuid__.uuid4()) if not __original_name_is_none: baseuri = cast(str, name) try: if _doc.get("items") is None: raise ValidationException("missing required field `items`", None, []) items = load_field( _doc.get("items"), uri_union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype_False_True_2_None, baseuri, loadingOptions, lc=_doc.get("items") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `items`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("items") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `items` field is not valid because:", SourceLine(_doc, "items", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `items` field is not valid because:", SourceLine(_doc, "items", str), [e], detailed_message=f"the `items` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("type") is None: raise ValidationException("missing required field `type`", None, []) type_ = load_field( _doc.get("type"), typedsl_Array_nameLoader_2, baseuri, loadingOptions, lc=_doc.get("type") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `type`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("type") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [e], detailed_message=f"the `type` field with value `{val}` " "is not valid because:", ) ) label = None if "label" in _doc: try: label = load_field( _doc.get("label"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("label") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `label`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("label") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [e], detailed_message=f"the `label` field with value `{val}` " "is not valid because:", ) ) doc = None if "doc" in _doc: try: doc = load_field( _doc.get("doc"), union_of_None_type_or_strtype_or_array_of_strtype, baseuri, loadingOptions, lc=_doc.get("doc") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `doc`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("doc") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [e], detailed_message=f"the `doc` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `items`, `type`, `label`, `doc`, `name`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( items=items, type_=type_, label=label, doc=doc, name=name, extension_fields=extension_fields, loadingOptions=loadingOptions, ) loadingOptions.idx[cast(str, name)] = (_constructed, loadingOptions) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.name is not None: u = save_relative_uri(self.name, base_url, True, None, relative_uris) r["name"] = u if self.items is not None: u = save_relative_uri(self.items, self.name, False, 2, relative_uris) r["items"] = u if self.type_ is not None: r["type"] = save( self.type_, top=False, base_url=self.name, relative_uris=relative_uris ) if self.label is not None: r["label"] = save( self.label, top=False, base_url=self.name, relative_uris=relative_uris ) if self.doc is not None: r["doc"] = save( self.doc, top=False, base_url=self.name, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["items", "type", "label", "doc", "name"]) class InputParameter(Parameter, InputFormat, LoadContents): pass class OutputParameter(Parameter, OutputFormat): pass class ProcessRequirement(Saveable): """ A process requirement declares a prerequisite that may or must be fulfilled before executing a process. See [`Process.hints`](#process) and [`Process.requirements`](#process). Process requirements are the primary mechanism for specifying extensions to the CWL core specification. """ pass class Process(Identified, Labeled, Documented): """ The base executable type in CWL is the `Process` object defined by the document. Note that the `Process` object is abstract and cannot be directly executed. """ pass class InlineJavascriptRequirement(ProcessRequirement): """ Indicates that the workflow platform must support inline Javascript expressions. If this requirement is not present, the workflow platform must not perform expression interpolatation. """ def __init__( self, expressionLib: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.class_ = "InlineJavascriptRequirement" self.expressionLib = expressionLib def __eq__(self, other: Any) -> bool: if isinstance(other, InlineJavascriptRequirement): return bool( self.class_ == other.class_ and self.expressionLib == other.expressionLib ) return False def __hash__(self) -> int: return hash((self.class_, self.expressionLib)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "InlineJavascriptRequirement": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("class") is None: raise ValidationException("missing required field `class`", None, []) class_ = load_field( _doc.get("class"), uri_InlineJavascriptRequirement_classLoader_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("class") ) if class_ not in (cls.__name__, loadingOptions.vocab.get(cls.__name__)): raise ValidationException(f"tried `{cls.__name__}` but") except ValidationException as e: raise e expressionLib = None if "expressionLib" in _doc: try: expressionLib = load_field( _doc.get("expressionLib"), union_of_None_type_or_array_of_strtype, baseuri, loadingOptions, lc=_doc.get("expressionLib") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `expressionLib`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("expressionLib") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `expressionLib` field is not valid because:", SourceLine(_doc, "expressionLib", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `expressionLib` field is not valid because:", SourceLine(_doc, "expressionLib", str), [e], detailed_message=f"the `expressionLib` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `class`, `expressionLib`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( expressionLib=expressionLib, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.class_ is not None: uri = self.loadingOptions.vocab[self.class_] if p := self.loadingOptions.rvocab.get(uri[: -len(self.class_)]): uri = f"{p}:{self.class_}" else: uri = self.class_ u = save_relative_uri(uri, base_url, False, None, relative_uris) r["class"] = u if self.expressionLib is not None: r["expressionLib"] = save( self.expressionLib, top=False, base_url=base_url, relative_uris=relative_uris, ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["class", "expressionLib"]) class CommandInputSchema(Saveable): pass class SchemaDefRequirement(ProcessRequirement): """ This field consists of an array of type definitions which must be used when interpreting the `inputs` and `outputs` fields. When a `type` field contain a IRI, the implementation must check if the type is defined in `schemaDefs` and use that definition. If the type is not found in `schemaDefs`, it is an error. The entries in `schemaDefs` must be processed in the order listed such that later schema definitions may refer to earlier schema definitions. """ def __init__( self, types: Any, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.class_ = "SchemaDefRequirement" self.types = types def __eq__(self, other: Any) -> bool: if isinstance(other, SchemaDefRequirement): return bool(self.class_ == other.class_ and self.types == other.types) return False def __hash__(self) -> int: return hash((self.class_, self.types)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "SchemaDefRequirement": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("class") is None: raise ValidationException("missing required field `class`", None, []) class_ = load_field( _doc.get("class"), uri_SchemaDefRequirement_classLoader_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("class") ) if class_ not in (cls.__name__, loadingOptions.vocab.get(cls.__name__)): raise ValidationException(f"tried `{cls.__name__}` but") except ValidationException as e: raise e try: if _doc.get("types") is None: raise ValidationException("missing required field `types`", None, []) types = load_field( _doc.get("types"), array_of_union_of_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader, baseuri, loadingOptions, lc=_doc.get("types") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `types`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("types") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `types` field is not valid because:", SourceLine(_doc, "types", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `types` field is not valid because:", SourceLine(_doc, "types", str), [e], detailed_message=f"the `types` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `class`, `types`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( types=types, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.class_ is not None: uri = self.loadingOptions.vocab[self.class_] if p := self.loadingOptions.rvocab.get(uri[: -len(self.class_)]): uri = f"{p}:{self.class_}" else: uri = self.class_ u = save_relative_uri(uri, base_url, False, None, relative_uris) r["class"] = u if self.types is not None: r["types"] = save( self.types, top=False, base_url=base_url, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["class", "types"]) class SecondaryFileSchema(Saveable): def __init__( self, pattern: Any, required: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.pattern = pattern self.required = required def __eq__(self, other: Any) -> bool: if isinstance(other, SecondaryFileSchema): return bool( self.pattern == other.pattern and self.required == other.required ) return False def __hash__(self) -> int: return hash((self.pattern, self.required)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "SecondaryFileSchema": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("pattern") is None: raise ValidationException("missing required field `pattern`", None, []) pattern = load_field( _doc.get("pattern"), union_of_strtype_or_ExpressionLoader, baseuri, loadingOptions, lc=_doc.get("pattern") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `pattern`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("pattern") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `pattern` field is not valid because:", SourceLine(_doc, "pattern", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `pattern` field is not valid because:", SourceLine(_doc, "pattern", str), [e], detailed_message=f"the `pattern` field with value `{val}` " "is not valid because:", ) ) required = None if "required" in _doc: try: required = load_field( _doc.get("required"), union_of_None_type_or_booltype_or_ExpressionLoader, baseuri, loadingOptions, lc=_doc.get("required") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `required`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("required") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `required` field is not valid because:", SourceLine(_doc, "required", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `required` field is not valid because:", SourceLine(_doc, "required", str), [e], detailed_message=f"the `required` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `pattern`, `required`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( pattern=pattern, required=required, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.pattern is not None: r["pattern"] = save( self.pattern, top=False, base_url=base_url, relative_uris=relative_uris ) if self.required is not None: r["required"] = save( self.required, top=False, base_url=base_url, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["pattern", "required"]) class LoadListingRequirement(ProcessRequirement): """ Specify the desired behavior for loading the `listing` field of a Directory object for use by expressions. """ def __init__( self, loadListing: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.class_ = "LoadListingRequirement" self.loadListing = loadListing def __eq__(self, other: Any) -> bool: if isinstance(other, LoadListingRequirement): return bool( self.class_ == other.class_ and self.loadListing == other.loadListing ) return False def __hash__(self) -> int: return hash((self.class_, self.loadListing)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "LoadListingRequirement": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("class") is None: raise ValidationException("missing required field `class`", None, []) class_ = load_field( _doc.get("class"), uri_LoadListingRequirement_classLoader_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("class") ) if class_ not in (cls.__name__, loadingOptions.vocab.get(cls.__name__)): raise ValidationException(f"tried `{cls.__name__}` but") except ValidationException as e: raise e loadListing = None if "loadListing" in _doc: try: loadListing = load_field( _doc.get("loadListing"), union_of_None_type_or_LoadListingEnumLoader, baseuri, loadingOptions, lc=_doc.get("loadListing") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `loadListing`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("loadListing") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `loadListing` field is not valid because:", SourceLine(_doc, "loadListing", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `loadListing` field is not valid because:", SourceLine(_doc, "loadListing", str), [e], detailed_message=f"the `loadListing` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `class`, `loadListing`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( loadListing=loadListing, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.class_ is not None: uri = self.loadingOptions.vocab[self.class_] if p := self.loadingOptions.rvocab.get(uri[: -len(self.class_)]): uri = f"{p}:{self.class_}" else: uri = self.class_ u = save_relative_uri(uri, base_url, False, None, relative_uris) r["class"] = u if self.loadListing is not None: r["loadListing"] = save( self.loadListing, top=False, base_url=base_url, relative_uris=relative_uris, ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["class", "loadListing"]) class EnvironmentDef(Saveable): """ Define an environment variable that will be set in the runtime environment by the workflow platform when executing the command line tool. May be the result of executing an expression, such as getting a parameter from input. """ def __init__( self, envName: Any, envValue: Any, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.envName = envName self.envValue = envValue def __eq__(self, other: Any) -> bool: if isinstance(other, EnvironmentDef): return bool( self.envName == other.envName and self.envValue == other.envValue ) return False def __hash__(self) -> int: return hash((self.envName, self.envValue)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "EnvironmentDef": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("envName") is None: raise ValidationException("missing required field `envName`", None, []) envName = load_field( _doc.get("envName"), strtype, baseuri, loadingOptions, lc=_doc.get("envName") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `envName`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("envName") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `envName` field is not valid because:", SourceLine(_doc, "envName", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `envName` field is not valid because:", SourceLine(_doc, "envName", str), [e], detailed_message=f"the `envName` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("envValue") is None: raise ValidationException("missing required field `envValue`", None, []) envValue = load_field( _doc.get("envValue"), union_of_strtype_or_ExpressionLoader, baseuri, loadingOptions, lc=_doc.get("envValue") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `envValue`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("envValue") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `envValue` field is not valid because:", SourceLine(_doc, "envValue", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `envValue` field is not valid because:", SourceLine(_doc, "envValue", str), [e], detailed_message=f"the `envValue` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `envName`, `envValue`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( envName=envName, envValue=envValue, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.envName is not None: r["envName"] = save( self.envName, top=False, base_url=base_url, relative_uris=relative_uris ) if self.envValue is not None: r["envValue"] = save( self.envValue, top=False, base_url=base_url, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["envName", "envValue"]) class CommandLineBinding(InputBinding): """ When listed under `inputBinding` in the input schema, the term "value" refers to the the corresponding value in the input object. For binding objects listed in `CommandLineTool.arguments`, the term "value" refers to the effective value after evaluating `valueFrom`. The binding behavior when building the command line depends on the data type of the value. If there is a mismatch between the type described by the input schema and the effective value, such as resulting from an expression evaluation, an implementation must use the data type of the effective value. - **string**: Add `prefix` and the string to the command line. - **number**: Add `prefix` and decimal representation to command line. - **boolean**: If true, add `prefix` to the command line. If false, add nothing. - **File**: Add `prefix` and the value of [`File.path`](#File) to the command line. - **Directory**: Add `prefix` and the value of [`Directory.path`](#Directory) to the command line. - **array**: If `itemSeparator` is specified, add `prefix` and the join the array into a single string with `itemSeparator` separating the items. Otherwise first add `prefix`, then recursively process individual elements. If the array is empty, it does not add anything to command line. - **object**: Add `prefix` only, and recursively add object fields for which `inputBinding` is specified. - **null**: Add nothing. """ def __init__( self, loadContents: Optional[Any] = None, position: Optional[Any] = None, prefix: Optional[Any] = None, separate: Optional[Any] = None, itemSeparator: Optional[Any] = None, valueFrom: Optional[Any] = None, shellQuote: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.loadContents = loadContents self.position = position self.prefix = prefix self.separate = separate self.itemSeparator = itemSeparator self.valueFrom = valueFrom self.shellQuote = shellQuote def __eq__(self, other: Any) -> bool: if isinstance(other, CommandLineBinding): return bool( self.loadContents == other.loadContents and self.position == other.position and self.prefix == other.prefix and self.separate == other.separate and self.itemSeparator == other.itemSeparator and self.valueFrom == other.valueFrom and self.shellQuote == other.shellQuote ) return False def __hash__(self) -> int: return hash( ( self.loadContents, self.position, self.prefix, self.separate, self.itemSeparator, self.valueFrom, self.shellQuote, ) ) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "CommandLineBinding": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] loadContents = None if "loadContents" in _doc: try: loadContents = load_field( _doc.get("loadContents"), union_of_None_type_or_booltype, baseuri, loadingOptions, lc=_doc.get("loadContents") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `loadContents`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("loadContents") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `loadContents` field is not valid because:", SourceLine(_doc, "loadContents", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `loadContents` field is not valid because:", SourceLine(_doc, "loadContents", str), [e], detailed_message=f"the `loadContents` field with value `{val}` " "is not valid because:", ) ) position = None if "position" in _doc: try: position = load_field( _doc.get("position"), union_of_None_type_or_inttype_or_ExpressionLoader, baseuri, loadingOptions, lc=_doc.get("position") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `position`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("position") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `position` field is not valid because:", SourceLine(_doc, "position", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `position` field is not valid because:", SourceLine(_doc, "position", str), [e], detailed_message=f"the `position` field with value `{val}` " "is not valid because:", ) ) prefix = None if "prefix" in _doc: try: prefix = load_field( _doc.get("prefix"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("prefix") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `prefix`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("prefix") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `prefix` field is not valid because:", SourceLine(_doc, "prefix", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `prefix` field is not valid because:", SourceLine(_doc, "prefix", str), [e], detailed_message=f"the `prefix` field with value `{val}` " "is not valid because:", ) ) separate = None if "separate" in _doc: try: separate = load_field( _doc.get("separate"), union_of_None_type_or_booltype, baseuri, loadingOptions, lc=_doc.get("separate") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `separate`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("separate") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `separate` field is not valid because:", SourceLine(_doc, "separate", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `separate` field is not valid because:", SourceLine(_doc, "separate", str), [e], detailed_message=f"the `separate` field with value `{val}` " "is not valid because:", ) ) itemSeparator = None if "itemSeparator" in _doc: try: itemSeparator = load_field( _doc.get("itemSeparator"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("itemSeparator") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `itemSeparator`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("itemSeparator") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `itemSeparator` field is not valid because:", SourceLine(_doc, "itemSeparator", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `itemSeparator` field is not valid because:", SourceLine(_doc, "itemSeparator", str), [e], detailed_message=f"the `itemSeparator` field with value `{val}` " "is not valid because:", ) ) valueFrom = None if "valueFrom" in _doc: try: valueFrom = load_field( _doc.get("valueFrom"), union_of_None_type_or_strtype_or_ExpressionLoader, baseuri, loadingOptions, lc=_doc.get("valueFrom") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `valueFrom`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("valueFrom") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `valueFrom` field is not valid because:", SourceLine(_doc, "valueFrom", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `valueFrom` field is not valid because:", SourceLine(_doc, "valueFrom", str), [e], detailed_message=f"the `valueFrom` field with value `{val}` " "is not valid because:", ) ) shellQuote = None if "shellQuote" in _doc: try: shellQuote = load_field( _doc.get("shellQuote"), union_of_None_type_or_booltype, baseuri, loadingOptions, lc=_doc.get("shellQuote") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `shellQuote`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("shellQuote") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `shellQuote` field is not valid because:", SourceLine(_doc, "shellQuote", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `shellQuote` field is not valid because:", SourceLine(_doc, "shellQuote", str), [e], detailed_message=f"the `shellQuote` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `loadContents`, `position`, `prefix`, `separate`, `itemSeparator`, `valueFrom`, `shellQuote`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( loadContents=loadContents, position=position, prefix=prefix, separate=separate, itemSeparator=itemSeparator, valueFrom=valueFrom, shellQuote=shellQuote, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.loadContents is not None: r["loadContents"] = save( self.loadContents, top=False, base_url=base_url, relative_uris=relative_uris, ) if self.position is not None: r["position"] = save( self.position, top=False, base_url=base_url, relative_uris=relative_uris ) if self.prefix is not None: r["prefix"] = save( self.prefix, top=False, base_url=base_url, relative_uris=relative_uris ) if self.separate is not None: r["separate"] = save( self.separate, top=False, base_url=base_url, relative_uris=relative_uris ) if self.itemSeparator is not None: r["itemSeparator"] = save( self.itemSeparator, top=False, base_url=base_url, relative_uris=relative_uris, ) if self.valueFrom is not None: r["valueFrom"] = save( self.valueFrom, top=False, base_url=base_url, relative_uris=relative_uris, ) if self.shellQuote is not None: r["shellQuote"] = save( self.shellQuote, top=False, base_url=base_url, relative_uris=relative_uris, ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset( [ "loadContents", "position", "prefix", "separate", "itemSeparator", "valueFrom", "shellQuote", ] ) class CommandOutputBinding(LoadContents): """ Describes how to generate an output parameter based on the files produced by a CommandLineTool. The output parameter value is generated by applying these operations in the following order: - glob - loadContents - outputEval - secondaryFiles """ def __init__( self, loadContents: Optional[Any] = None, loadListing: Optional[Any] = None, glob: Optional[Any] = None, outputEval: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.loadContents = loadContents self.loadListing = loadListing self.glob = glob self.outputEval = outputEval def __eq__(self, other: Any) -> bool: if isinstance(other, CommandOutputBinding): return bool( self.loadContents == other.loadContents and self.loadListing == other.loadListing and self.glob == other.glob and self.outputEval == other.outputEval ) return False def __hash__(self) -> int: return hash((self.loadContents, self.loadListing, self.glob, self.outputEval)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "CommandOutputBinding": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] loadContents = None if "loadContents" in _doc: try: loadContents = load_field( _doc.get("loadContents"), union_of_None_type_or_booltype, baseuri, loadingOptions, lc=_doc.get("loadContents") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `loadContents`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("loadContents") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `loadContents` field is not valid because:", SourceLine(_doc, "loadContents", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `loadContents` field is not valid because:", SourceLine(_doc, "loadContents", str), [e], detailed_message=f"the `loadContents` field with value `{val}` " "is not valid because:", ) ) loadListing = None if "loadListing" in _doc: try: loadListing = load_field( _doc.get("loadListing"), union_of_None_type_or_LoadListingEnumLoader, baseuri, loadingOptions, lc=_doc.get("loadListing") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `loadListing`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("loadListing") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `loadListing` field is not valid because:", SourceLine(_doc, "loadListing", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `loadListing` field is not valid because:", SourceLine(_doc, "loadListing", str), [e], detailed_message=f"the `loadListing` field with value `{val}` " "is not valid because:", ) ) glob = None if "glob" in _doc: try: glob = load_field( _doc.get("glob"), union_of_None_type_or_strtype_or_ExpressionLoader_or_array_of_strtype, baseuri, loadingOptions, lc=_doc.get("glob") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `glob`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("glob") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `glob` field is not valid because:", SourceLine(_doc, "glob", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `glob` field is not valid because:", SourceLine(_doc, "glob", str), [e], detailed_message=f"the `glob` field with value `{val}` " "is not valid because:", ) ) outputEval = None if "outputEval" in _doc: try: outputEval = load_field( _doc.get("outputEval"), union_of_None_type_or_ExpressionLoader, baseuri, loadingOptions, lc=_doc.get("outputEval") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `outputEval`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("outputEval") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `outputEval` field is not valid because:", SourceLine(_doc, "outputEval", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `outputEval` field is not valid because:", SourceLine(_doc, "outputEval", str), [e], detailed_message=f"the `outputEval` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `loadContents`, `loadListing`, `glob`, `outputEval`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( loadContents=loadContents, loadListing=loadListing, glob=glob, outputEval=outputEval, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.loadContents is not None: r["loadContents"] = save( self.loadContents, top=False, base_url=base_url, relative_uris=relative_uris, ) if self.loadListing is not None: r["loadListing"] = save( self.loadListing, top=False, base_url=base_url, relative_uris=relative_uris, ) if self.glob is not None: r["glob"] = save( self.glob, top=False, base_url=base_url, relative_uris=relative_uris ) if self.outputEval is not None: r["outputEval"] = save( self.outputEval, top=False, base_url=base_url, relative_uris=relative_uris, ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["loadContents", "loadListing", "glob", "outputEval"]) class CommandLineBindable(Saveable): pass class CommandInputRecordField(InputRecordField, CommandLineBindable): name: str def __init__( self, name: Any, type_: Any, doc: Optional[Any] = None, label: Optional[Any] = None, secondaryFiles: Optional[Any] = None, streamable: Optional[Any] = None, format: Optional[Any] = None, loadContents: Optional[Any] = None, loadListing: Optional[Any] = None, inputBinding: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.doc = doc self.name = name if name is not None else "_:" + str(_uuid__.uuid4()) self.type_ = type_ self.label = label self.secondaryFiles = secondaryFiles self.streamable = streamable self.format = format self.loadContents = loadContents self.loadListing = loadListing self.inputBinding = inputBinding def __eq__(self, other: Any) -> bool: if isinstance(other, CommandInputRecordField): return bool( self.doc == other.doc and self.name == other.name and self.type_ == other.type_ and self.label == other.label and self.secondaryFiles == other.secondaryFiles and self.streamable == other.streamable and self.format == other.format and self.loadContents == other.loadContents and self.loadListing == other.loadListing and self.inputBinding == other.inputBinding ) return False def __hash__(self) -> int: return hash( ( self.doc, self.name, self.type_, self.label, self.secondaryFiles, self.streamable, self.format, self.loadContents, self.loadListing, self.inputBinding, ) ) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "CommandInputRecordField": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] name = None if "name" in _doc: try: name = load_field( _doc.get("name"), uri_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("name") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `name`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("name") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [e], detailed_message=f"the `name` field with value `{val}` " "is not valid because:", ) ) __original_name_is_none = name is None if name is None: if docRoot is not None: name = docRoot else: _errors__.append(ValidationException("missing name")) if not __original_name_is_none: baseuri = cast(str, name) doc = None if "doc" in _doc: try: doc = load_field( _doc.get("doc"), union_of_None_type_or_strtype_or_array_of_strtype, baseuri, loadingOptions, lc=_doc.get("doc") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `doc`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("doc") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [e], detailed_message=f"the `doc` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("type") is None: raise ValidationException("missing required field `type`", None, []) type_ = load_field( _doc.get("type"), typedsl_union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype_2, baseuri, loadingOptions, lc=_doc.get("type") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `type`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("type") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [e], detailed_message=f"the `type` field with value `{val}` " "is not valid because:", ) ) label = None if "label" in _doc: try: label = load_field( _doc.get("label"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("label") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `label`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("label") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [e], detailed_message=f"the `label` field with value `{val}` " "is not valid because:", ) ) secondaryFiles = None if "secondaryFiles" in _doc: try: secondaryFiles = load_field( _doc.get("secondaryFiles"), secondaryfilesdsl_union_of_None_type_or_SecondaryFileSchemaLoader_or_array_of_SecondaryFileSchemaLoader, baseuri, loadingOptions, lc=_doc.get("secondaryFiles") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `secondaryFiles`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("secondaryFiles") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `secondaryFiles` field is not valid because:", SourceLine(_doc, "secondaryFiles", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `secondaryFiles` field is not valid because:", SourceLine(_doc, "secondaryFiles", str), [e], detailed_message=f"the `secondaryFiles` field with value `{val}` " "is not valid because:", ) ) streamable = None if "streamable" in _doc: try: streamable = load_field( _doc.get("streamable"), union_of_None_type_or_booltype, baseuri, loadingOptions, lc=_doc.get("streamable") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `streamable`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("streamable") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `streamable` field is not valid because:", SourceLine(_doc, "streamable", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `streamable` field is not valid because:", SourceLine(_doc, "streamable", str), [e], detailed_message=f"the `streamable` field with value `{val}` " "is not valid because:", ) ) format = None if "format" in _doc: try: format = load_field( _doc.get("format"), uri_union_of_None_type_or_strtype_or_array_of_strtype_or_ExpressionLoader_True_False_None_True, baseuri, loadingOptions, lc=_doc.get("format") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `format`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("format") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `format` field is not valid because:", SourceLine(_doc, "format", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `format` field is not valid because:", SourceLine(_doc, "format", str), [e], detailed_message=f"the `format` field with value `{val}` " "is not valid because:", ) ) loadContents = None if "loadContents" in _doc: try: loadContents = load_field( _doc.get("loadContents"), union_of_None_type_or_booltype, baseuri, loadingOptions, lc=_doc.get("loadContents") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `loadContents`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("loadContents") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `loadContents` field is not valid because:", SourceLine(_doc, "loadContents", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `loadContents` field is not valid because:", SourceLine(_doc, "loadContents", str), [e], detailed_message=f"the `loadContents` field with value `{val}` " "is not valid because:", ) ) loadListing = None if "loadListing" in _doc: try: loadListing = load_field( _doc.get("loadListing"), union_of_None_type_or_LoadListingEnumLoader, baseuri, loadingOptions, lc=_doc.get("loadListing") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `loadListing`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("loadListing") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `loadListing` field is not valid because:", SourceLine(_doc, "loadListing", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `loadListing` field is not valid because:", SourceLine(_doc, "loadListing", str), [e], detailed_message=f"the `loadListing` field with value `{val}` " "is not valid because:", ) ) inputBinding = None if "inputBinding" in _doc: try: inputBinding = load_field( _doc.get("inputBinding"), union_of_None_type_or_CommandLineBindingLoader, baseuri, loadingOptions, lc=_doc.get("inputBinding") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `inputBinding`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("inputBinding") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `inputBinding` field is not valid because:", SourceLine(_doc, "inputBinding", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `inputBinding` field is not valid because:", SourceLine(_doc, "inputBinding", str), [e], detailed_message=f"the `inputBinding` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `doc`, `name`, `type`, `label`, `secondaryFiles`, `streamable`, `format`, `loadContents`, `loadListing`, `inputBinding`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( doc=doc, name=name, type_=type_, label=label, secondaryFiles=secondaryFiles, streamable=streamable, format=format, loadContents=loadContents, loadListing=loadListing, inputBinding=inputBinding, extension_fields=extension_fields, loadingOptions=loadingOptions, ) loadingOptions.idx[cast(str, name)] = (_constructed, loadingOptions) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.name is not None: u = save_relative_uri(self.name, base_url, True, None, relative_uris) r["name"] = u if self.doc is not None: r["doc"] = save( self.doc, top=False, base_url=self.name, relative_uris=relative_uris ) if self.type_ is not None: r["type"] = save( self.type_, top=False, base_url=self.name, relative_uris=relative_uris ) if self.label is not None: r["label"] = save( self.label, top=False, base_url=self.name, relative_uris=relative_uris ) if self.secondaryFiles is not None: r["secondaryFiles"] = save( self.secondaryFiles, top=False, base_url=self.name, relative_uris=relative_uris, ) if self.streamable is not None: r["streamable"] = save( self.streamable, top=False, base_url=self.name, relative_uris=relative_uris, ) if self.format is not None: u = save_relative_uri(self.format, self.name, True, None, relative_uris) r["format"] = u if self.loadContents is not None: r["loadContents"] = save( self.loadContents, top=False, base_url=self.name, relative_uris=relative_uris, ) if self.loadListing is not None: r["loadListing"] = save( self.loadListing, top=False, base_url=self.name, relative_uris=relative_uris, ) if self.inputBinding is not None: r["inputBinding"] = save( self.inputBinding, top=False, base_url=self.name, relative_uris=relative_uris, ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset( [ "doc", "name", "type", "label", "secondaryFiles", "streamable", "format", "loadContents", "loadListing", "inputBinding", ] ) class CommandInputRecordSchema( InputRecordSchema, CommandInputSchema, CommandLineBindable ): name: str def __init__( self, type_: Any, fields: Optional[Any] = None, label: Optional[Any] = None, doc: Optional[Any] = None, name: Optional[Any] = None, inputBinding: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.fields = fields self.type_ = type_ self.label = label self.doc = doc self.name = name if name is not None else "_:" + str(_uuid__.uuid4()) self.inputBinding = inputBinding def __eq__(self, other: Any) -> bool: if isinstance(other, CommandInputRecordSchema): return bool( self.fields == other.fields and self.type_ == other.type_ and self.label == other.label and self.doc == other.doc and self.name == other.name and self.inputBinding == other.inputBinding ) return False def __hash__(self) -> int: return hash( ( self.fields, self.type_, self.label, self.doc, self.name, self.inputBinding, ) ) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "CommandInputRecordSchema": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] name = None if "name" in _doc: try: name = load_field( _doc.get("name"), uri_union_of_None_type_or_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("name") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `name`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("name") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [e], detailed_message=f"the `name` field with value `{val}` " "is not valid because:", ) ) __original_name_is_none = name is None if name is None: if docRoot is not None: name = docRoot else: name = "_:" + str(_uuid__.uuid4()) if not __original_name_is_none: baseuri = cast(str, name) fields = None if "fields" in _doc: try: fields = load_field( _doc.get("fields"), idmap_fields_union_of_None_type_or_array_of_CommandInputRecordFieldLoader, baseuri, loadingOptions, lc=_doc.get("fields") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `fields`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("fields") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `fields` field is not valid because:", SourceLine(_doc, "fields", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `fields` field is not valid because:", SourceLine(_doc, "fields", str), [e], detailed_message=f"the `fields` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("type") is None: raise ValidationException("missing required field `type`", None, []) type_ = load_field( _doc.get("type"), typedsl_Record_nameLoader_2, baseuri, loadingOptions, lc=_doc.get("type") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `type`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("type") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [e], detailed_message=f"the `type` field with value `{val}` " "is not valid because:", ) ) label = None if "label" in _doc: try: label = load_field( _doc.get("label"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("label") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `label`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("label") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [e], detailed_message=f"the `label` field with value `{val}` " "is not valid because:", ) ) doc = None if "doc" in _doc: try: doc = load_field( _doc.get("doc"), union_of_None_type_or_strtype_or_array_of_strtype, baseuri, loadingOptions, lc=_doc.get("doc") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `doc`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("doc") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [e], detailed_message=f"the `doc` field with value `{val}` " "is not valid because:", ) ) inputBinding = None if "inputBinding" in _doc: try: inputBinding = load_field( _doc.get("inputBinding"), union_of_None_type_or_CommandLineBindingLoader, baseuri, loadingOptions, lc=_doc.get("inputBinding") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `inputBinding`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("inputBinding") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `inputBinding` field is not valid because:", SourceLine(_doc, "inputBinding", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `inputBinding` field is not valid because:", SourceLine(_doc, "inputBinding", str), [e], detailed_message=f"the `inputBinding` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `fields`, `type`, `label`, `doc`, `name`, `inputBinding`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( fields=fields, type_=type_, label=label, doc=doc, name=name, inputBinding=inputBinding, extension_fields=extension_fields, loadingOptions=loadingOptions, ) loadingOptions.idx[cast(str, name)] = (_constructed, loadingOptions) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.name is not None: u = save_relative_uri(self.name, base_url, True, None, relative_uris) r["name"] = u if self.fields is not None: r["fields"] = save( self.fields, top=False, base_url=self.name, relative_uris=relative_uris ) if self.type_ is not None: r["type"] = save( self.type_, top=False, base_url=self.name, relative_uris=relative_uris ) if self.label is not None: r["label"] = save( self.label, top=False, base_url=self.name, relative_uris=relative_uris ) if self.doc is not None: r["doc"] = save( self.doc, top=False, base_url=self.name, relative_uris=relative_uris ) if self.inputBinding is not None: r["inputBinding"] = save( self.inputBinding, top=False, base_url=self.name, relative_uris=relative_uris, ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["fields", "type", "label", "doc", "name", "inputBinding"]) class CommandInputEnumSchema(InputEnumSchema, CommandInputSchema, CommandLineBindable): name: str def __init__( self, symbols: Any, type_: Any, name: Optional[Any] = None, label: Optional[Any] = None, doc: Optional[Any] = None, inputBinding: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.name = name if name is not None else "_:" + str(_uuid__.uuid4()) self.symbols = symbols self.type_ = type_ self.label = label self.doc = doc self.inputBinding = inputBinding def __eq__(self, other: Any) -> bool: if isinstance(other, CommandInputEnumSchema): return bool( self.name == other.name and self.symbols == other.symbols and self.type_ == other.type_ and self.label == other.label and self.doc == other.doc and self.inputBinding == other.inputBinding ) return False def __hash__(self) -> int: return hash( ( self.name, self.symbols, self.type_, self.label, self.doc, self.inputBinding, ) ) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "CommandInputEnumSchema": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] name = None if "name" in _doc: try: name = load_field( _doc.get("name"), uri_union_of_None_type_or_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("name") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `name`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("name") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [e], detailed_message=f"the `name` field with value `{val}` " "is not valid because:", ) ) __original_name_is_none = name is None if name is None: if docRoot is not None: name = docRoot else: name = "_:" + str(_uuid__.uuid4()) if not __original_name_is_none: baseuri = cast(str, name) try: if _doc.get("symbols") is None: raise ValidationException("missing required field `symbols`", None, []) symbols = load_field( _doc.get("symbols"), uri_array_of_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("symbols") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `symbols`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("symbols") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `symbols` field is not valid because:", SourceLine(_doc, "symbols", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `symbols` field is not valid because:", SourceLine(_doc, "symbols", str), [e], detailed_message=f"the `symbols` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("type") is None: raise ValidationException("missing required field `type`", None, []) type_ = load_field( _doc.get("type"), typedsl_Enum_nameLoader_2, baseuri, loadingOptions, lc=_doc.get("type") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `type`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("type") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [e], detailed_message=f"the `type` field with value `{val}` " "is not valid because:", ) ) label = None if "label" in _doc: try: label = load_field( _doc.get("label"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("label") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `label`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("label") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [e], detailed_message=f"the `label` field with value `{val}` " "is not valid because:", ) ) doc = None if "doc" in _doc: try: doc = load_field( _doc.get("doc"), union_of_None_type_or_strtype_or_array_of_strtype, baseuri, loadingOptions, lc=_doc.get("doc") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `doc`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("doc") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [e], detailed_message=f"the `doc` field with value `{val}` " "is not valid because:", ) ) inputBinding = None if "inputBinding" in _doc: try: inputBinding = load_field( _doc.get("inputBinding"), union_of_None_type_or_CommandLineBindingLoader, baseuri, loadingOptions, lc=_doc.get("inputBinding") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `inputBinding`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("inputBinding") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `inputBinding` field is not valid because:", SourceLine(_doc, "inputBinding", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `inputBinding` field is not valid because:", SourceLine(_doc, "inputBinding", str), [e], detailed_message=f"the `inputBinding` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `name`, `symbols`, `type`, `label`, `doc`, `inputBinding`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( name=name, symbols=symbols, type_=type_, label=label, doc=doc, inputBinding=inputBinding, extension_fields=extension_fields, loadingOptions=loadingOptions, ) loadingOptions.idx[cast(str, name)] = (_constructed, loadingOptions) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.name is not None: u = save_relative_uri(self.name, base_url, True, None, relative_uris) r["name"] = u if self.symbols is not None: u = save_relative_uri(self.symbols, self.name, True, None, relative_uris) r["symbols"] = u if self.type_ is not None: r["type"] = save( self.type_, top=False, base_url=self.name, relative_uris=relative_uris ) if self.label is not None: r["label"] = save( self.label, top=False, base_url=self.name, relative_uris=relative_uris ) if self.doc is not None: r["doc"] = save( self.doc, top=False, base_url=self.name, relative_uris=relative_uris ) if self.inputBinding is not None: r["inputBinding"] = save( self.inputBinding, top=False, base_url=self.name, relative_uris=relative_uris, ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["name", "symbols", "type", "label", "doc", "inputBinding"]) class CommandInputArraySchema( InputArraySchema, CommandInputSchema, CommandLineBindable ): name: str def __init__( self, items: Any, type_: Any, label: Optional[Any] = None, doc: Optional[Any] = None, name: Optional[Any] = None, inputBinding: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.items = items self.type_ = type_ self.label = label self.doc = doc self.name = name if name is not None else "_:" + str(_uuid__.uuid4()) self.inputBinding = inputBinding def __eq__(self, other: Any) -> bool: if isinstance(other, CommandInputArraySchema): return bool( self.items == other.items and self.type_ == other.type_ and self.label == other.label and self.doc == other.doc and self.name == other.name and self.inputBinding == other.inputBinding ) return False def __hash__(self) -> int: return hash( (self.items, self.type_, self.label, self.doc, self.name, self.inputBinding) ) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "CommandInputArraySchema": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] name = None if "name" in _doc: try: name = load_field( _doc.get("name"), uri_union_of_None_type_or_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("name") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `name`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("name") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [e], detailed_message=f"the `name` field with value `{val}` " "is not valid because:", ) ) __original_name_is_none = name is None if name is None: if docRoot is not None: name = docRoot else: name = "_:" + str(_uuid__.uuid4()) if not __original_name_is_none: baseuri = cast(str, name) try: if _doc.get("items") is None: raise ValidationException("missing required field `items`", None, []) items = load_field( _doc.get("items"), uri_union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype_False_True_2_None, baseuri, loadingOptions, lc=_doc.get("items") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `items`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("items") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `items` field is not valid because:", SourceLine(_doc, "items", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `items` field is not valid because:", SourceLine(_doc, "items", str), [e], detailed_message=f"the `items` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("type") is None: raise ValidationException("missing required field `type`", None, []) type_ = load_field( _doc.get("type"), typedsl_Array_nameLoader_2, baseuri, loadingOptions, lc=_doc.get("type") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `type`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("type") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [e], detailed_message=f"the `type` field with value `{val}` " "is not valid because:", ) ) label = None if "label" in _doc: try: label = load_field( _doc.get("label"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("label") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `label`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("label") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [e], detailed_message=f"the `label` field with value `{val}` " "is not valid because:", ) ) doc = None if "doc" in _doc: try: doc = load_field( _doc.get("doc"), union_of_None_type_or_strtype_or_array_of_strtype, baseuri, loadingOptions, lc=_doc.get("doc") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `doc`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("doc") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [e], detailed_message=f"the `doc` field with value `{val}` " "is not valid because:", ) ) inputBinding = None if "inputBinding" in _doc: try: inputBinding = load_field( _doc.get("inputBinding"), union_of_None_type_or_CommandLineBindingLoader, baseuri, loadingOptions, lc=_doc.get("inputBinding") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `inputBinding`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("inputBinding") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `inputBinding` field is not valid because:", SourceLine(_doc, "inputBinding", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `inputBinding` field is not valid because:", SourceLine(_doc, "inputBinding", str), [e], detailed_message=f"the `inputBinding` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `items`, `type`, `label`, `doc`, `name`, `inputBinding`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( items=items, type_=type_, label=label, doc=doc, name=name, inputBinding=inputBinding, extension_fields=extension_fields, loadingOptions=loadingOptions, ) loadingOptions.idx[cast(str, name)] = (_constructed, loadingOptions) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.name is not None: u = save_relative_uri(self.name, base_url, True, None, relative_uris) r["name"] = u if self.items is not None: u = save_relative_uri(self.items, self.name, False, 2, relative_uris) r["items"] = u if self.type_ is not None: r["type"] = save( self.type_, top=False, base_url=self.name, relative_uris=relative_uris ) if self.label is not None: r["label"] = save( self.label, top=False, base_url=self.name, relative_uris=relative_uris ) if self.doc is not None: r["doc"] = save( self.doc, top=False, base_url=self.name, relative_uris=relative_uris ) if self.inputBinding is not None: r["inputBinding"] = save( self.inputBinding, top=False, base_url=self.name, relative_uris=relative_uris, ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["items", "type", "label", "doc", "name", "inputBinding"]) class CommandOutputRecordField(OutputRecordField): name: str def __init__( self, name: Any, type_: Any, doc: Optional[Any] = None, label: Optional[Any] = None, secondaryFiles: Optional[Any] = None, streamable: Optional[Any] = None, format: Optional[Any] = None, outputBinding: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.doc = doc self.name = name if name is not None else "_:" + str(_uuid__.uuid4()) self.type_ = type_ self.label = label self.secondaryFiles = secondaryFiles self.streamable = streamable self.format = format self.outputBinding = outputBinding def __eq__(self, other: Any) -> bool: if isinstance(other, CommandOutputRecordField): return bool( self.doc == other.doc and self.name == other.name and self.type_ == other.type_ and self.label == other.label and self.secondaryFiles == other.secondaryFiles and self.streamable == other.streamable and self.format == other.format and self.outputBinding == other.outputBinding ) return False def __hash__(self) -> int: return hash( ( self.doc, self.name, self.type_, self.label, self.secondaryFiles, self.streamable, self.format, self.outputBinding, ) ) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "CommandOutputRecordField": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] name = None if "name" in _doc: try: name = load_field( _doc.get("name"), uri_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("name") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `name`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("name") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [e], detailed_message=f"the `name` field with value `{val}` " "is not valid because:", ) ) __original_name_is_none = name is None if name is None: if docRoot is not None: name = docRoot else: _errors__.append(ValidationException("missing name")) if not __original_name_is_none: baseuri = cast(str, name) doc = None if "doc" in _doc: try: doc = load_field( _doc.get("doc"), union_of_None_type_or_strtype_or_array_of_strtype, baseuri, loadingOptions, lc=_doc.get("doc") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `doc`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("doc") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [e], detailed_message=f"the `doc` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("type") is None: raise ValidationException("missing required field `type`", None, []) type_ = load_field( _doc.get("type"), typedsl_union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype_2, baseuri, loadingOptions, lc=_doc.get("type") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `type`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("type") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [e], detailed_message=f"the `type` field with value `{val}` " "is not valid because:", ) ) label = None if "label" in _doc: try: label = load_field( _doc.get("label"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("label") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `label`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("label") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [e], detailed_message=f"the `label` field with value `{val}` " "is not valid because:", ) ) secondaryFiles = None if "secondaryFiles" in _doc: try: secondaryFiles = load_field( _doc.get("secondaryFiles"), secondaryfilesdsl_union_of_None_type_or_SecondaryFileSchemaLoader_or_array_of_SecondaryFileSchemaLoader, baseuri, loadingOptions, lc=_doc.get("secondaryFiles") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `secondaryFiles`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("secondaryFiles") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `secondaryFiles` field is not valid because:", SourceLine(_doc, "secondaryFiles", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `secondaryFiles` field is not valid because:", SourceLine(_doc, "secondaryFiles", str), [e], detailed_message=f"the `secondaryFiles` field with value `{val}` " "is not valid because:", ) ) streamable = None if "streamable" in _doc: try: streamable = load_field( _doc.get("streamable"), union_of_None_type_or_booltype, baseuri, loadingOptions, lc=_doc.get("streamable") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `streamable`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("streamable") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `streamable` field is not valid because:", SourceLine(_doc, "streamable", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `streamable` field is not valid because:", SourceLine(_doc, "streamable", str), [e], detailed_message=f"the `streamable` field with value `{val}` " "is not valid because:", ) ) format = None if "format" in _doc: try: format = load_field( _doc.get("format"), uri_union_of_None_type_or_strtype_or_ExpressionLoader_True_False_None_True, baseuri, loadingOptions, lc=_doc.get("format") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `format`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("format") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `format` field is not valid because:", SourceLine(_doc, "format", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `format` field is not valid because:", SourceLine(_doc, "format", str), [e], detailed_message=f"the `format` field with value `{val}` " "is not valid because:", ) ) outputBinding = None if "outputBinding" in _doc: try: outputBinding = load_field( _doc.get("outputBinding"), union_of_None_type_or_CommandOutputBindingLoader, baseuri, loadingOptions, lc=_doc.get("outputBinding") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `outputBinding`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("outputBinding") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `outputBinding` field is not valid because:", SourceLine(_doc, "outputBinding", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `outputBinding` field is not valid because:", SourceLine(_doc, "outputBinding", str), [e], detailed_message=f"the `outputBinding` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `doc`, `name`, `type`, `label`, `secondaryFiles`, `streamable`, `format`, `outputBinding`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( doc=doc, name=name, type_=type_, label=label, secondaryFiles=secondaryFiles, streamable=streamable, format=format, outputBinding=outputBinding, extension_fields=extension_fields, loadingOptions=loadingOptions, ) loadingOptions.idx[cast(str, name)] = (_constructed, loadingOptions) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.name is not None: u = save_relative_uri(self.name, base_url, True, None, relative_uris) r["name"] = u if self.doc is not None: r["doc"] = save( self.doc, top=False, base_url=self.name, relative_uris=relative_uris ) if self.type_ is not None: r["type"] = save( self.type_, top=False, base_url=self.name, relative_uris=relative_uris ) if self.label is not None: r["label"] = save( self.label, top=False, base_url=self.name, relative_uris=relative_uris ) if self.secondaryFiles is not None: r["secondaryFiles"] = save( self.secondaryFiles, top=False, base_url=self.name, relative_uris=relative_uris, ) if self.streamable is not None: r["streamable"] = save( self.streamable, top=False, base_url=self.name, relative_uris=relative_uris, ) if self.format is not None: u = save_relative_uri(self.format, self.name, True, None, relative_uris) r["format"] = u if self.outputBinding is not None: r["outputBinding"] = save( self.outputBinding, top=False, base_url=self.name, relative_uris=relative_uris, ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset( [ "doc", "name", "type", "label", "secondaryFiles", "streamable", "format", "outputBinding", ] ) class CommandOutputRecordSchema(OutputRecordSchema): name: str def __init__( self, type_: Any, fields: Optional[Any] = None, label: Optional[Any] = None, doc: Optional[Any] = None, name: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.fields = fields self.type_ = type_ self.label = label self.doc = doc self.name = name if name is not None else "_:" + str(_uuid__.uuid4()) def __eq__(self, other: Any) -> bool: if isinstance(other, CommandOutputRecordSchema): return bool( self.fields == other.fields and self.type_ == other.type_ and self.label == other.label and self.doc == other.doc and self.name == other.name ) return False def __hash__(self) -> int: return hash((self.fields, self.type_, self.label, self.doc, self.name)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "CommandOutputRecordSchema": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] name = None if "name" in _doc: try: name = load_field( _doc.get("name"), uri_union_of_None_type_or_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("name") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `name`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("name") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [e], detailed_message=f"the `name` field with value `{val}` " "is not valid because:", ) ) __original_name_is_none = name is None if name is None: if docRoot is not None: name = docRoot else: name = "_:" + str(_uuid__.uuid4()) if not __original_name_is_none: baseuri = cast(str, name) fields = None if "fields" in _doc: try: fields = load_field( _doc.get("fields"), idmap_fields_union_of_None_type_or_array_of_CommandOutputRecordFieldLoader, baseuri, loadingOptions, lc=_doc.get("fields") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `fields`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("fields") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `fields` field is not valid because:", SourceLine(_doc, "fields", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `fields` field is not valid because:", SourceLine(_doc, "fields", str), [e], detailed_message=f"the `fields` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("type") is None: raise ValidationException("missing required field `type`", None, []) type_ = load_field( _doc.get("type"), typedsl_Record_nameLoader_2, baseuri, loadingOptions, lc=_doc.get("type") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `type`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("type") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [e], detailed_message=f"the `type` field with value `{val}` " "is not valid because:", ) ) label = None if "label" in _doc: try: label = load_field( _doc.get("label"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("label") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `label`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("label") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [e], detailed_message=f"the `label` field with value `{val}` " "is not valid because:", ) ) doc = None if "doc" in _doc: try: doc = load_field( _doc.get("doc"), union_of_None_type_or_strtype_or_array_of_strtype, baseuri, loadingOptions, lc=_doc.get("doc") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `doc`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("doc") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [e], detailed_message=f"the `doc` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `fields`, `type`, `label`, `doc`, `name`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( fields=fields, type_=type_, label=label, doc=doc, name=name, extension_fields=extension_fields, loadingOptions=loadingOptions, ) loadingOptions.idx[cast(str, name)] = (_constructed, loadingOptions) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.name is not None: u = save_relative_uri(self.name, base_url, True, None, relative_uris) r["name"] = u if self.fields is not None: r["fields"] = save( self.fields, top=False, base_url=self.name, relative_uris=relative_uris ) if self.type_ is not None: r["type"] = save( self.type_, top=False, base_url=self.name, relative_uris=relative_uris ) if self.label is not None: r["label"] = save( self.label, top=False, base_url=self.name, relative_uris=relative_uris ) if self.doc is not None: r["doc"] = save( self.doc, top=False, base_url=self.name, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["fields", "type", "label", "doc", "name"]) class CommandOutputEnumSchema(OutputEnumSchema): name: str def __init__( self, symbols: Any, type_: Any, name: Optional[Any] = None, label: Optional[Any] = None, doc: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.name = name if name is not None else "_:" + str(_uuid__.uuid4()) self.symbols = symbols self.type_ = type_ self.label = label self.doc = doc def __eq__(self, other: Any) -> bool: if isinstance(other, CommandOutputEnumSchema): return bool( self.name == other.name and self.symbols == other.symbols and self.type_ == other.type_ and self.label == other.label and self.doc == other.doc ) return False def __hash__(self) -> int: return hash((self.name, self.symbols, self.type_, self.label, self.doc)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "CommandOutputEnumSchema": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] name = None if "name" in _doc: try: name = load_field( _doc.get("name"), uri_union_of_None_type_or_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("name") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `name`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("name") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [e], detailed_message=f"the `name` field with value `{val}` " "is not valid because:", ) ) __original_name_is_none = name is None if name is None: if docRoot is not None: name = docRoot else: name = "_:" + str(_uuid__.uuid4()) if not __original_name_is_none: baseuri = cast(str, name) try: if _doc.get("symbols") is None: raise ValidationException("missing required field `symbols`", None, []) symbols = load_field( _doc.get("symbols"), uri_array_of_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("symbols") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `symbols`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("symbols") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `symbols` field is not valid because:", SourceLine(_doc, "symbols", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `symbols` field is not valid because:", SourceLine(_doc, "symbols", str), [e], detailed_message=f"the `symbols` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("type") is None: raise ValidationException("missing required field `type`", None, []) type_ = load_field( _doc.get("type"), typedsl_Enum_nameLoader_2, baseuri, loadingOptions, lc=_doc.get("type") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `type`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("type") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [e], detailed_message=f"the `type` field with value `{val}` " "is not valid because:", ) ) label = None if "label" in _doc: try: label = load_field( _doc.get("label"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("label") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `label`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("label") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [e], detailed_message=f"the `label` field with value `{val}` " "is not valid because:", ) ) doc = None if "doc" in _doc: try: doc = load_field( _doc.get("doc"), union_of_None_type_or_strtype_or_array_of_strtype, baseuri, loadingOptions, lc=_doc.get("doc") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `doc`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("doc") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [e], detailed_message=f"the `doc` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `name`, `symbols`, `type`, `label`, `doc`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( name=name, symbols=symbols, type_=type_, label=label, doc=doc, extension_fields=extension_fields, loadingOptions=loadingOptions, ) loadingOptions.idx[cast(str, name)] = (_constructed, loadingOptions) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.name is not None: u = save_relative_uri(self.name, base_url, True, None, relative_uris) r["name"] = u if self.symbols is not None: u = save_relative_uri(self.symbols, self.name, True, None, relative_uris) r["symbols"] = u if self.type_ is not None: r["type"] = save( self.type_, top=False, base_url=self.name, relative_uris=relative_uris ) if self.label is not None: r["label"] = save( self.label, top=False, base_url=self.name, relative_uris=relative_uris ) if self.doc is not None: r["doc"] = save( self.doc, top=False, base_url=self.name, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["name", "symbols", "type", "label", "doc"]) class CommandOutputArraySchema(OutputArraySchema): name: str def __init__( self, items: Any, type_: Any, label: Optional[Any] = None, doc: Optional[Any] = None, name: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.items = items self.type_ = type_ self.label = label self.doc = doc self.name = name if name is not None else "_:" + str(_uuid__.uuid4()) def __eq__(self, other: Any) -> bool: if isinstance(other, CommandOutputArraySchema): return bool( self.items == other.items and self.type_ == other.type_ and self.label == other.label and self.doc == other.doc and self.name == other.name ) return False def __hash__(self) -> int: return hash((self.items, self.type_, self.label, self.doc, self.name)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "CommandOutputArraySchema": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] name = None if "name" in _doc: try: name = load_field( _doc.get("name"), uri_union_of_None_type_or_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("name") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `name`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("name") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [e], detailed_message=f"the `name` field with value `{val}` " "is not valid because:", ) ) __original_name_is_none = name is None if name is None: if docRoot is not None: name = docRoot else: name = "_:" + str(_uuid__.uuid4()) if not __original_name_is_none: baseuri = cast(str, name) try: if _doc.get("items") is None: raise ValidationException("missing required field `items`", None, []) items = load_field( _doc.get("items"), uri_union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype_False_True_2_None, baseuri, loadingOptions, lc=_doc.get("items") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `items`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("items") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `items` field is not valid because:", SourceLine(_doc, "items", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `items` field is not valid because:", SourceLine(_doc, "items", str), [e], detailed_message=f"the `items` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("type") is None: raise ValidationException("missing required field `type`", None, []) type_ = load_field( _doc.get("type"), typedsl_Array_nameLoader_2, baseuri, loadingOptions, lc=_doc.get("type") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `type`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("type") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [e], detailed_message=f"the `type` field with value `{val}` " "is not valid because:", ) ) label = None if "label" in _doc: try: label = load_field( _doc.get("label"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("label") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `label`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("label") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [e], detailed_message=f"the `label` field with value `{val}` " "is not valid because:", ) ) doc = None if "doc" in _doc: try: doc = load_field( _doc.get("doc"), union_of_None_type_or_strtype_or_array_of_strtype, baseuri, loadingOptions, lc=_doc.get("doc") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `doc`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("doc") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [e], detailed_message=f"the `doc` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `items`, `type`, `label`, `doc`, `name`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( items=items, type_=type_, label=label, doc=doc, name=name, extension_fields=extension_fields, loadingOptions=loadingOptions, ) loadingOptions.idx[cast(str, name)] = (_constructed, loadingOptions) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.name is not None: u = save_relative_uri(self.name, base_url, True, None, relative_uris) r["name"] = u if self.items is not None: u = save_relative_uri(self.items, self.name, False, 2, relative_uris) r["items"] = u if self.type_ is not None: r["type"] = save( self.type_, top=False, base_url=self.name, relative_uris=relative_uris ) if self.label is not None: r["label"] = save( self.label, top=False, base_url=self.name, relative_uris=relative_uris ) if self.doc is not None: r["doc"] = save( self.doc, top=False, base_url=self.name, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["items", "type", "label", "doc", "name"]) class CommandInputParameter(InputParameter): """ An input parameter for a CommandLineTool. """ id: str def __init__( self, id: Any, type_: Any, label: Optional[Any] = None, secondaryFiles: Optional[Any] = None, streamable: Optional[Any] = None, doc: Optional[Any] = None, format: Optional[Any] = None, loadContents: Optional[Any] = None, loadListing: Optional[Any] = None, default: Optional[Any] = None, inputBinding: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.label = label self.secondaryFiles = secondaryFiles self.streamable = streamable self.doc = doc self.id = id if id is not None else "_:" + str(_uuid__.uuid4()) self.format = format self.loadContents = loadContents self.loadListing = loadListing self.default = default self.type_ = type_ self.inputBinding = inputBinding def __eq__(self, other: Any) -> bool: if isinstance(other, CommandInputParameter): return bool( self.label == other.label and self.secondaryFiles == other.secondaryFiles and self.streamable == other.streamable and self.doc == other.doc and self.id == other.id and self.format == other.format and self.loadContents == other.loadContents and self.loadListing == other.loadListing and self.default == other.default and self.type_ == other.type_ and self.inputBinding == other.inputBinding ) return False def __hash__(self) -> int: return hash( ( self.label, self.secondaryFiles, self.streamable, self.doc, self.id, self.format, self.loadContents, self.loadListing, self.default, self.type_, self.inputBinding, ) ) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "CommandInputParameter": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] id = None if "id" in _doc: try: id = load_field( _doc.get("id"), uri_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("id") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `id`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("id") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `id` field is not valid because:", SourceLine(_doc, "id", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `id` field is not valid because:", SourceLine(_doc, "id", str), [e], detailed_message=f"the `id` field with value `{val}` " "is not valid because:", ) ) __original_id_is_none = id is None if id is None: if docRoot is not None: id = docRoot else: _errors__.append(ValidationException("missing id")) if not __original_id_is_none: baseuri = cast(str, id) label = None if "label" in _doc: try: label = load_field( _doc.get("label"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("label") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `label`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("label") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [e], detailed_message=f"the `label` field with value `{val}` " "is not valid because:", ) ) secondaryFiles = None if "secondaryFiles" in _doc: try: secondaryFiles = load_field( _doc.get("secondaryFiles"), secondaryfilesdsl_union_of_None_type_or_SecondaryFileSchemaLoader_or_array_of_SecondaryFileSchemaLoader, baseuri, loadingOptions, lc=_doc.get("secondaryFiles") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `secondaryFiles`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("secondaryFiles") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `secondaryFiles` field is not valid because:", SourceLine(_doc, "secondaryFiles", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `secondaryFiles` field is not valid because:", SourceLine(_doc, "secondaryFiles", str), [e], detailed_message=f"the `secondaryFiles` field with value `{val}` " "is not valid because:", ) ) streamable = None if "streamable" in _doc: try: streamable = load_field( _doc.get("streamable"), union_of_None_type_or_booltype, baseuri, loadingOptions, lc=_doc.get("streamable") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `streamable`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("streamable") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `streamable` field is not valid because:", SourceLine(_doc, "streamable", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `streamable` field is not valid because:", SourceLine(_doc, "streamable", str), [e], detailed_message=f"the `streamable` field with value `{val}` " "is not valid because:", ) ) doc = None if "doc" in _doc: try: doc = load_field( _doc.get("doc"), union_of_None_type_or_strtype_or_array_of_strtype, baseuri, loadingOptions, lc=_doc.get("doc") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `doc`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("doc") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [e], detailed_message=f"the `doc` field with value `{val}` " "is not valid because:", ) ) format = None if "format" in _doc: try: format = load_field( _doc.get("format"), uri_union_of_None_type_or_strtype_or_array_of_strtype_or_ExpressionLoader_True_False_None_True, baseuri, loadingOptions, lc=_doc.get("format") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `format`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("format") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `format` field is not valid because:", SourceLine(_doc, "format", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `format` field is not valid because:", SourceLine(_doc, "format", str), [e], detailed_message=f"the `format` field with value `{val}` " "is not valid because:", ) ) loadContents = None if "loadContents" in _doc: try: loadContents = load_field( _doc.get("loadContents"), union_of_None_type_or_booltype, baseuri, loadingOptions, lc=_doc.get("loadContents") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `loadContents`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("loadContents") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `loadContents` field is not valid because:", SourceLine(_doc, "loadContents", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `loadContents` field is not valid because:", SourceLine(_doc, "loadContents", str), [e], detailed_message=f"the `loadContents` field with value `{val}` " "is not valid because:", ) ) loadListing = None if "loadListing" in _doc: try: loadListing = load_field( _doc.get("loadListing"), union_of_None_type_or_LoadListingEnumLoader, baseuri, loadingOptions, lc=_doc.get("loadListing") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `loadListing`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("loadListing") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `loadListing` field is not valid because:", SourceLine(_doc, "loadListing", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `loadListing` field is not valid because:", SourceLine(_doc, "loadListing", str), [e], detailed_message=f"the `loadListing` field with value `{val}` " "is not valid because:", ) ) default = None if "default" in _doc: try: default = load_field( _doc.get("default"), union_of_None_type_or_CWLObjectTypeLoader, baseuri, loadingOptions, lc=_doc.get("default") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `default`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("default") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `default` field is not valid because:", SourceLine(_doc, "default", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `default` field is not valid because:", SourceLine(_doc, "default", str), [e], detailed_message=f"the `default` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("type") is None: raise ValidationException("missing required field `type`", None, []) type_ = load_field( _doc.get("type"), typedsl_union_of_CWLTypeLoader_or_stdinLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype_2, baseuri, loadingOptions, lc=_doc.get("type") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `type`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("type") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [e], detailed_message=f"the `type` field with value `{val}` " "is not valid because:", ) ) inputBinding = None if "inputBinding" in _doc: try: inputBinding = load_field( _doc.get("inputBinding"), union_of_None_type_or_CommandLineBindingLoader, baseuri, loadingOptions, lc=_doc.get("inputBinding") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `inputBinding`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("inputBinding") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `inputBinding` field is not valid because:", SourceLine(_doc, "inputBinding", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `inputBinding` field is not valid because:", SourceLine(_doc, "inputBinding", str), [e], detailed_message=f"the `inputBinding` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `label`, `secondaryFiles`, `streamable`, `doc`, `id`, `format`, `loadContents`, `loadListing`, `default`, `type`, `inputBinding`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( label=label, secondaryFiles=secondaryFiles, streamable=streamable, doc=doc, id=id, format=format, loadContents=loadContents, loadListing=loadListing, default=default, type_=type_, inputBinding=inputBinding, extension_fields=extension_fields, loadingOptions=loadingOptions, ) loadingOptions.idx[cast(str, id)] = (_constructed, loadingOptions) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.id is not None: u = save_relative_uri(self.id, base_url, True, None, relative_uris) r["id"] = u if self.label is not None: r["label"] = save( self.label, top=False, base_url=self.id, relative_uris=relative_uris ) if self.secondaryFiles is not None: r["secondaryFiles"] = save( self.secondaryFiles, top=False, base_url=self.id, relative_uris=relative_uris, ) if self.streamable is not None: r["streamable"] = save( self.streamable, top=False, base_url=self.id, relative_uris=relative_uris, ) if self.doc is not None: r["doc"] = save( self.doc, top=False, base_url=self.id, relative_uris=relative_uris ) if self.format is not None: u = save_relative_uri(self.format, self.id, True, None, relative_uris) r["format"] = u if self.loadContents is not None: r["loadContents"] = save( self.loadContents, top=False, base_url=self.id, relative_uris=relative_uris, ) if self.loadListing is not None: r["loadListing"] = save( self.loadListing, top=False, base_url=self.id, relative_uris=relative_uris, ) if self.default is not None: r["default"] = save( self.default, top=False, base_url=self.id, relative_uris=relative_uris ) if self.type_ is not None: r["type"] = save( self.type_, top=False, base_url=self.id, relative_uris=relative_uris ) if self.inputBinding is not None: r["inputBinding"] = save( self.inputBinding, top=False, base_url=self.id, relative_uris=relative_uris, ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset( [ "label", "secondaryFiles", "streamable", "doc", "id", "format", "loadContents", "loadListing", "default", "type", "inputBinding", ] ) class CommandOutputParameter(OutputParameter): """ An output parameter for a CommandLineTool. """ id: str def __init__( self, id: Any, type_: Any, label: Optional[Any] = None, secondaryFiles: Optional[Any] = None, streamable: Optional[Any] = None, doc: Optional[Any] = None, format: Optional[Any] = None, outputBinding: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.label = label self.secondaryFiles = secondaryFiles self.streamable = streamable self.doc = doc self.id = id if id is not None else "_:" + str(_uuid__.uuid4()) self.format = format self.type_ = type_ self.outputBinding = outputBinding def __eq__(self, other: Any) -> bool: if isinstance(other, CommandOutputParameter): return bool( self.label == other.label and self.secondaryFiles == other.secondaryFiles and self.streamable == other.streamable and self.doc == other.doc and self.id == other.id and self.format == other.format and self.type_ == other.type_ and self.outputBinding == other.outputBinding ) return False def __hash__(self) -> int: return hash( ( self.label, self.secondaryFiles, self.streamable, self.doc, self.id, self.format, self.type_, self.outputBinding, ) ) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "CommandOutputParameter": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] id = None if "id" in _doc: try: id = load_field( _doc.get("id"), uri_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("id") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `id`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("id") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `id` field is not valid because:", SourceLine(_doc, "id", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `id` field is not valid because:", SourceLine(_doc, "id", str), [e], detailed_message=f"the `id` field with value `{val}` " "is not valid because:", ) ) __original_id_is_none = id is None if id is None: if docRoot is not None: id = docRoot else: _errors__.append(ValidationException("missing id")) if not __original_id_is_none: baseuri = cast(str, id) label = None if "label" in _doc: try: label = load_field( _doc.get("label"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("label") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `label`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("label") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [e], detailed_message=f"the `label` field with value `{val}` " "is not valid because:", ) ) secondaryFiles = None if "secondaryFiles" in _doc: try: secondaryFiles = load_field( _doc.get("secondaryFiles"), secondaryfilesdsl_union_of_None_type_or_SecondaryFileSchemaLoader_or_array_of_SecondaryFileSchemaLoader, baseuri, loadingOptions, lc=_doc.get("secondaryFiles") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `secondaryFiles`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("secondaryFiles") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `secondaryFiles` field is not valid because:", SourceLine(_doc, "secondaryFiles", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `secondaryFiles` field is not valid because:", SourceLine(_doc, "secondaryFiles", str), [e], detailed_message=f"the `secondaryFiles` field with value `{val}` " "is not valid because:", ) ) streamable = None if "streamable" in _doc: try: streamable = load_field( _doc.get("streamable"), union_of_None_type_or_booltype, baseuri, loadingOptions, lc=_doc.get("streamable") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `streamable`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("streamable") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `streamable` field is not valid because:", SourceLine(_doc, "streamable", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `streamable` field is not valid because:", SourceLine(_doc, "streamable", str), [e], detailed_message=f"the `streamable` field with value `{val}` " "is not valid because:", ) ) doc = None if "doc" in _doc: try: doc = load_field( _doc.get("doc"), union_of_None_type_or_strtype_or_array_of_strtype, baseuri, loadingOptions, lc=_doc.get("doc") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `doc`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("doc") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [e], detailed_message=f"the `doc` field with value `{val}` " "is not valid because:", ) ) format = None if "format" in _doc: try: format = load_field( _doc.get("format"), uri_union_of_None_type_or_strtype_or_ExpressionLoader_True_False_None_True, baseuri, loadingOptions, lc=_doc.get("format") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `format`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("format") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `format` field is not valid because:", SourceLine(_doc, "format", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `format` field is not valid because:", SourceLine(_doc, "format", str), [e], detailed_message=f"the `format` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("type") is None: raise ValidationException("missing required field `type`", None, []) type_ = load_field( _doc.get("type"), typedsl_union_of_CWLTypeLoader_or_stdoutLoader_or_stderrLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype_2, baseuri, loadingOptions, lc=_doc.get("type") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `type`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("type") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [e], detailed_message=f"the `type` field with value `{val}` " "is not valid because:", ) ) outputBinding = None if "outputBinding" in _doc: try: outputBinding = load_field( _doc.get("outputBinding"), union_of_None_type_or_CommandOutputBindingLoader, baseuri, loadingOptions, lc=_doc.get("outputBinding") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `outputBinding`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("outputBinding") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `outputBinding` field is not valid because:", SourceLine(_doc, "outputBinding", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `outputBinding` field is not valid because:", SourceLine(_doc, "outputBinding", str), [e], detailed_message=f"the `outputBinding` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `label`, `secondaryFiles`, `streamable`, `doc`, `id`, `format`, `type`, `outputBinding`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( label=label, secondaryFiles=secondaryFiles, streamable=streamable, doc=doc, id=id, format=format, type_=type_, outputBinding=outputBinding, extension_fields=extension_fields, loadingOptions=loadingOptions, ) loadingOptions.idx[cast(str, id)] = (_constructed, loadingOptions) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.id is not None: u = save_relative_uri(self.id, base_url, True, None, relative_uris) r["id"] = u if self.label is not None: r["label"] = save( self.label, top=False, base_url=self.id, relative_uris=relative_uris ) if self.secondaryFiles is not None: r["secondaryFiles"] = save( self.secondaryFiles, top=False, base_url=self.id, relative_uris=relative_uris, ) if self.streamable is not None: r["streamable"] = save( self.streamable, top=False, base_url=self.id, relative_uris=relative_uris, ) if self.doc is not None: r["doc"] = save( self.doc, top=False, base_url=self.id, relative_uris=relative_uris ) if self.format is not None: u = save_relative_uri(self.format, self.id, True, None, relative_uris) r["format"] = u if self.type_ is not None: r["type"] = save( self.type_, top=False, base_url=self.id, relative_uris=relative_uris ) if self.outputBinding is not None: r["outputBinding"] = save( self.outputBinding, top=False, base_url=self.id, relative_uris=relative_uris, ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset( [ "label", "secondaryFiles", "streamable", "doc", "id", "format", "type", "outputBinding", ] ) class CommandLineTool(Process): """ This defines the schema of the CWL Command Line Tool Description document. """ id: str def __init__( self, inputs: Any, outputs: Any, id: Optional[Any] = None, label: Optional[Any] = None, doc: Optional[Any] = None, requirements: Optional[Any] = None, hints: Optional[Any] = None, cwlVersion: Optional[Any] = None, baseCommand: Optional[Any] = None, arguments: Optional[Any] = None, stdin: Optional[Any] = None, stderr: Optional[Any] = None, stdout: Optional[Any] = None, successCodes: Optional[Any] = None, temporaryFailCodes: Optional[Any] = None, permanentFailCodes: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.id = id if id is not None else "_:" + str(_uuid__.uuid4()) self.label = label self.doc = doc self.inputs = inputs self.outputs = outputs self.requirements = requirements self.hints = hints self.cwlVersion = cwlVersion self.class_ = "CommandLineTool" self.baseCommand = baseCommand self.arguments = arguments self.stdin = stdin self.stderr = stderr self.stdout = stdout self.successCodes = successCodes self.temporaryFailCodes = temporaryFailCodes self.permanentFailCodes = permanentFailCodes def __eq__(self, other: Any) -> bool: if isinstance(other, CommandLineTool): return bool( self.id == other.id and self.label == other.label and self.doc == other.doc and self.inputs == other.inputs and self.outputs == other.outputs and self.requirements == other.requirements and self.hints == other.hints and self.cwlVersion == other.cwlVersion and self.class_ == other.class_ and self.baseCommand == other.baseCommand and self.arguments == other.arguments and self.stdin == other.stdin and self.stderr == other.stderr and self.stdout == other.stdout and self.successCodes == other.successCodes and self.temporaryFailCodes == other.temporaryFailCodes and self.permanentFailCodes == other.permanentFailCodes ) return False def __hash__(self) -> int: return hash( ( self.id, self.label, self.doc, self.inputs, self.outputs, self.requirements, self.hints, self.cwlVersion, self.class_, self.baseCommand, self.arguments, self.stdin, self.stderr, self.stdout, self.successCodes, self.temporaryFailCodes, self.permanentFailCodes, ) ) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "CommandLineTool": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] id = None if "id" in _doc: try: id = load_field( _doc.get("id"), uri_union_of_None_type_or_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("id") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `id`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("id") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `id` field is not valid because:", SourceLine(_doc, "id", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `id` field is not valid because:", SourceLine(_doc, "id", str), [e], detailed_message=f"the `id` field with value `{val}` " "is not valid because:", ) ) __original_id_is_none = id is None if id is None: if docRoot is not None: id = docRoot else: id = "_:" + str(_uuid__.uuid4()) if not __original_id_is_none: baseuri = cast(str, id) try: if _doc.get("class") is None: raise ValidationException("missing required field `class`", None, []) class_ = load_field( _doc.get("class"), uri_CommandLineTool_classLoader_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("class") ) if class_ not in (cls.__name__, loadingOptions.vocab.get(cls.__name__)): raise ValidationException(f"tried `{cls.__name__}` but") except ValidationException as e: raise e label = None if "label" in _doc: try: label = load_field( _doc.get("label"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("label") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `label`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("label") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [e], detailed_message=f"the `label` field with value `{val}` " "is not valid because:", ) ) doc = None if "doc" in _doc: try: doc = load_field( _doc.get("doc"), union_of_None_type_or_strtype_or_array_of_strtype, baseuri, loadingOptions, lc=_doc.get("doc") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `doc`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("doc") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [e], detailed_message=f"the `doc` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("inputs") is None: raise ValidationException("missing required field `inputs`", None, []) inputs = load_field( _doc.get("inputs"), idmap_inputs_array_of_CommandInputParameterLoader, baseuri, loadingOptions, lc=_doc.get("inputs") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `inputs`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("inputs") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `inputs` field is not valid because:", SourceLine(_doc, "inputs", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `inputs` field is not valid because:", SourceLine(_doc, "inputs", str), [e], detailed_message=f"the `inputs` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("outputs") is None: raise ValidationException("missing required field `outputs`", None, []) outputs = load_field( _doc.get("outputs"), idmap_outputs_array_of_CommandOutputParameterLoader, baseuri, loadingOptions, lc=_doc.get("outputs") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `outputs`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("outputs") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `outputs` field is not valid because:", SourceLine(_doc, "outputs", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `outputs` field is not valid because:", SourceLine(_doc, "outputs", str), [e], detailed_message=f"the `outputs` field with value `{val}` " "is not valid because:", ) ) requirements = None if "requirements" in _doc: try: requirements = load_field( _doc.get("requirements"), idmap_requirements_union_of_None_type_or_array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_LoadListingRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_WorkReuseLoader_or_NetworkAccessLoader_or_InplaceUpdateRequirementLoader_or_ToolTimeLimitLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader_or_SecretsLoader_or_MPIRequirementLoader_or_CUDARequirementLoader_or_ShmSizeLoader, baseuri, loadingOptions, lc=_doc.get("requirements") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `requirements`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("requirements") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `requirements` field is not valid because:", SourceLine(_doc, "requirements", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `requirements` field is not valid because:", SourceLine(_doc, "requirements", str), [e], detailed_message=f"the `requirements` field with value `{val}` " "is not valid because:", ) ) hints = None if "hints" in _doc: try: hints = load_field( _doc.get("hints"), idmap_hints_union_of_None_type_or_array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_LoadListingRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_WorkReuseLoader_or_NetworkAccessLoader_or_InplaceUpdateRequirementLoader_or_ToolTimeLimitLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader_or_SecretsLoader_or_MPIRequirementLoader_or_CUDARequirementLoader_or_ShmSizeLoader_or_Any_type, baseuri, loadingOptions, lc=_doc.get("hints") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `hints`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("hints") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `hints` field is not valid because:", SourceLine(_doc, "hints", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `hints` field is not valid because:", SourceLine(_doc, "hints", str), [e], detailed_message=f"the `hints` field with value `{val}` " "is not valid because:", ) ) cwlVersion = None if "cwlVersion" in _doc: try: cwlVersion = load_field( _doc.get("cwlVersion"), uri_union_of_None_type_or_CWLVersionLoader_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("cwlVersion") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `cwlVersion`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("cwlVersion") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `cwlVersion` field is not valid because:", SourceLine(_doc, "cwlVersion", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `cwlVersion` field is not valid because:", SourceLine(_doc, "cwlVersion", str), [e], detailed_message=f"the `cwlVersion` field with value `{val}` " "is not valid because:", ) ) baseCommand = None if "baseCommand" in _doc: try: baseCommand = load_field( _doc.get("baseCommand"), union_of_None_type_or_strtype_or_array_of_strtype, baseuri, loadingOptions, lc=_doc.get("baseCommand") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `baseCommand`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("baseCommand") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `baseCommand` field is not valid because:", SourceLine(_doc, "baseCommand", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `baseCommand` field is not valid because:", SourceLine(_doc, "baseCommand", str), [e], detailed_message=f"the `baseCommand` field with value `{val}` " "is not valid because:", ) ) arguments = None if "arguments" in _doc: try: arguments = load_field( _doc.get("arguments"), union_of_None_type_or_array_of_union_of_strtype_or_ExpressionLoader_or_CommandLineBindingLoader, baseuri, loadingOptions, lc=_doc.get("arguments") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `arguments`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("arguments") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `arguments` field is not valid because:", SourceLine(_doc, "arguments", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `arguments` field is not valid because:", SourceLine(_doc, "arguments", str), [e], detailed_message=f"the `arguments` field with value `{val}` " "is not valid because:", ) ) stdin = None if "stdin" in _doc: try: stdin = load_field( _doc.get("stdin"), union_of_None_type_or_strtype_or_ExpressionLoader, baseuri, loadingOptions, lc=_doc.get("stdin") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `stdin`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("stdin") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `stdin` field is not valid because:", SourceLine(_doc, "stdin", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `stdin` field is not valid because:", SourceLine(_doc, "stdin", str), [e], detailed_message=f"the `stdin` field with value `{val}` " "is not valid because:", ) ) stderr = None if "stderr" in _doc: try: stderr = load_field( _doc.get("stderr"), union_of_None_type_or_strtype_or_ExpressionLoader, baseuri, loadingOptions, lc=_doc.get("stderr") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `stderr`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("stderr") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `stderr` field is not valid because:", SourceLine(_doc, "stderr", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `stderr` field is not valid because:", SourceLine(_doc, "stderr", str), [e], detailed_message=f"the `stderr` field with value `{val}` " "is not valid because:", ) ) stdout = None if "stdout" in _doc: try: stdout = load_field( _doc.get("stdout"), union_of_None_type_or_strtype_or_ExpressionLoader, baseuri, loadingOptions, lc=_doc.get("stdout") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `stdout`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("stdout") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `stdout` field is not valid because:", SourceLine(_doc, "stdout", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `stdout` field is not valid because:", SourceLine(_doc, "stdout", str), [e], detailed_message=f"the `stdout` field with value `{val}` " "is not valid because:", ) ) successCodes = None if "successCodes" in _doc: try: successCodes = load_field( _doc.get("successCodes"), union_of_None_type_or_array_of_inttype, baseuri, loadingOptions, lc=_doc.get("successCodes") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `successCodes`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("successCodes") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `successCodes` field is not valid because:", SourceLine(_doc, "successCodes", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `successCodes` field is not valid because:", SourceLine(_doc, "successCodes", str), [e], detailed_message=f"the `successCodes` field with value `{val}` " "is not valid because:", ) ) temporaryFailCodes = None if "temporaryFailCodes" in _doc: try: temporaryFailCodes = load_field( _doc.get("temporaryFailCodes"), union_of_None_type_or_array_of_inttype, baseuri, loadingOptions, lc=_doc.get("temporaryFailCodes") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `temporaryFailCodes`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("temporaryFailCodes") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `temporaryFailCodes` field is not valid because:", SourceLine(_doc, "temporaryFailCodes", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `temporaryFailCodes` field is not valid because:", SourceLine(_doc, "temporaryFailCodes", str), [e], detailed_message=f"the `temporaryFailCodes` field with value `{val}` " "is not valid because:", ) ) permanentFailCodes = None if "permanentFailCodes" in _doc: try: permanentFailCodes = load_field( _doc.get("permanentFailCodes"), union_of_None_type_or_array_of_inttype, baseuri, loadingOptions, lc=_doc.get("permanentFailCodes") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `permanentFailCodes`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("permanentFailCodes") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `permanentFailCodes` field is not valid because:", SourceLine(_doc, "permanentFailCodes", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `permanentFailCodes` field is not valid because:", SourceLine(_doc, "permanentFailCodes", str), [e], detailed_message=f"the `permanentFailCodes` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `id`, `label`, `doc`, `inputs`, `outputs`, `requirements`, `hints`, `cwlVersion`, `class`, `baseCommand`, `arguments`, `stdin`, `stderr`, `stdout`, `successCodes`, `temporaryFailCodes`, `permanentFailCodes`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( id=id, label=label, doc=doc, inputs=inputs, outputs=outputs, requirements=requirements, hints=hints, cwlVersion=cwlVersion, baseCommand=baseCommand, arguments=arguments, stdin=stdin, stderr=stderr, stdout=stdout, successCodes=successCodes, temporaryFailCodes=temporaryFailCodes, permanentFailCodes=permanentFailCodes, extension_fields=extension_fields, loadingOptions=loadingOptions, ) loadingOptions.idx[cast(str, id)] = (_constructed, loadingOptions) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.id is not None: u = save_relative_uri(self.id, base_url, True, None, relative_uris) r["id"] = u if self.class_ is not None: uri = self.loadingOptions.vocab[self.class_] if p := self.loadingOptions.rvocab.get(uri[: -len(self.class_)]): uri = f"{p}:{self.class_}" else: uri = self.class_ u = save_relative_uri(uri, self.id, False, None, relative_uris) r["class"] = u if self.label is not None: r["label"] = save( self.label, top=False, base_url=self.id, relative_uris=relative_uris ) if self.doc is not None: r["doc"] = save( self.doc, top=False, base_url=self.id, relative_uris=relative_uris ) if self.inputs is not None: r["inputs"] = save( self.inputs, top=False, base_url=self.id, relative_uris=relative_uris ) if self.outputs is not None: r["outputs"] = save( self.outputs, top=False, base_url=self.id, relative_uris=relative_uris ) if self.requirements is not None: r["requirements"] = save( self.requirements, top=False, base_url=self.id, relative_uris=relative_uris, ) if self.hints is not None: r["hints"] = save( self.hints, top=False, base_url=self.id, relative_uris=relative_uris ) if self.cwlVersion is not None: u = save_relative_uri(self.cwlVersion, self.id, False, None, relative_uris) r["cwlVersion"] = u if self.baseCommand is not None: r["baseCommand"] = save( self.baseCommand, top=False, base_url=self.id, relative_uris=relative_uris, ) if self.arguments is not None: r["arguments"] = save( self.arguments, top=False, base_url=self.id, relative_uris=relative_uris ) if self.stdin is not None: r["stdin"] = save( self.stdin, top=False, base_url=self.id, relative_uris=relative_uris ) if self.stderr is not None: r["stderr"] = save( self.stderr, top=False, base_url=self.id, relative_uris=relative_uris ) if self.stdout is not None: r["stdout"] = save( self.stdout, top=False, base_url=self.id, relative_uris=relative_uris ) if self.successCodes is not None: r["successCodes"] = save( self.successCodes, top=False, base_url=self.id, relative_uris=relative_uris, ) if self.temporaryFailCodes is not None: r["temporaryFailCodes"] = save( self.temporaryFailCodes, top=False, base_url=self.id, relative_uris=relative_uris, ) if self.permanentFailCodes is not None: r["permanentFailCodes"] = save( self.permanentFailCodes, top=False, base_url=self.id, relative_uris=relative_uris, ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset( [ "id", "label", "doc", "inputs", "outputs", "requirements", "hints", "cwlVersion", "class", "baseCommand", "arguments", "stdin", "stderr", "stdout", "successCodes", "temporaryFailCodes", "permanentFailCodes", ] ) class DockerRequirement(ProcessRequirement): """ Indicates that a workflow component should be run in a [Docker](http://docker.com) or Docker-compatible (such as [Singularity](https://www.sylabs.io/) and [udocker](https://github.com/indigo-dc/udocker)) container environment and specifies how to fetch or build the image. If a CommandLineTool lists `DockerRequirement` under `hints` (or `requirements`), it may (or must) be run in the specified Docker container. The platform must first acquire or install the correct Docker image as specified by `dockerPull`, `dockerImport`, `dockerLoad` or `dockerFile`. The platform must execute the tool in the container using `docker run` with the appropriate Docker image and tool command line. The workflow platform may provide input files and the designated output directory through the use of volume bind mounts. The platform should rewrite file paths in the input object to correspond to the Docker bind mounted locations. That is, the platform should rewrite values in the parameter context such as `runtime.outdir`, `runtime.tmpdir` and others to be valid paths within the container. The platform must ensure that `runtime.outdir` and `runtime.tmpdir` are distinct directories. When running a tool contained in Docker, the workflow platform must not assume anything about the contents of the Docker container, such as the presence or absence of specific software, except to assume that the generated command line represents a valid command within the runtime environment of the container. A container image may specify an [ENTRYPOINT](https://docs.docker.com/engine/reference/builder/#entrypoint) and/or [CMD](https://docs.docker.com/engine/reference/builder/#cmd). Command line arguments will be appended after all elements of ENTRYPOINT, and will override all elements specified using CMD (in other words, CMD is only used when the CommandLineTool definition produces an empty command line). Use of implicit ENTRYPOINT or CMD are discouraged due to reproducibility concerns of the implicit hidden execution point (For further discussion, see [https://doi.org/10.12688/f1000research.15140.1](https://doi.org/10.12688/f1000research.15140.1)). Portable CommandLineTool wrappers in which use of a container is optional must not rely on ENTRYPOINT or CMD. CommandLineTools which do rely on ENTRYPOINT or CMD must list `DockerRequirement` in the `requirements` section. ## Interaction with other requirements If [EnvVarRequirement](#EnvVarRequirement) is specified alongside a DockerRequirement, the environment variables must be provided to Docker using `--env` or `--env-file` and interact with the container's preexisting environment as defined by Docker. """ def __init__( self, dockerPull: Optional[Any] = None, dockerLoad: Optional[Any] = None, dockerFile: Optional[Any] = None, dockerImport: Optional[Any] = None, dockerImageId: Optional[Any] = None, dockerOutputDirectory: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.class_ = "DockerRequirement" self.dockerPull = dockerPull self.dockerLoad = dockerLoad self.dockerFile = dockerFile self.dockerImport = dockerImport self.dockerImageId = dockerImageId self.dockerOutputDirectory = dockerOutputDirectory def __eq__(self, other: Any) -> bool: if isinstance(other, DockerRequirement): return bool( self.class_ == other.class_ and self.dockerPull == other.dockerPull and self.dockerLoad == other.dockerLoad and self.dockerFile == other.dockerFile and self.dockerImport == other.dockerImport and self.dockerImageId == other.dockerImageId and self.dockerOutputDirectory == other.dockerOutputDirectory ) return False def __hash__(self) -> int: return hash( ( self.class_, self.dockerPull, self.dockerLoad, self.dockerFile, self.dockerImport, self.dockerImageId, self.dockerOutputDirectory, ) ) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "DockerRequirement": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("class") is None: raise ValidationException("missing required field `class`", None, []) class_ = load_field( _doc.get("class"), uri_DockerRequirement_classLoader_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("class") ) if class_ not in (cls.__name__, loadingOptions.vocab.get(cls.__name__)): raise ValidationException(f"tried `{cls.__name__}` but") except ValidationException as e: raise e dockerPull = None if "dockerPull" in _doc: try: dockerPull = load_field( _doc.get("dockerPull"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("dockerPull") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `dockerPull`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("dockerPull") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `dockerPull` field is not valid because:", SourceLine(_doc, "dockerPull", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `dockerPull` field is not valid because:", SourceLine(_doc, "dockerPull", str), [e], detailed_message=f"the `dockerPull` field with value `{val}` " "is not valid because:", ) ) dockerLoad = None if "dockerLoad" in _doc: try: dockerLoad = load_field( _doc.get("dockerLoad"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("dockerLoad") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `dockerLoad`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("dockerLoad") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `dockerLoad` field is not valid because:", SourceLine(_doc, "dockerLoad", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `dockerLoad` field is not valid because:", SourceLine(_doc, "dockerLoad", str), [e], detailed_message=f"the `dockerLoad` field with value `{val}` " "is not valid because:", ) ) dockerFile = None if "dockerFile" in _doc: try: dockerFile = load_field( _doc.get("dockerFile"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("dockerFile") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `dockerFile`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("dockerFile") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `dockerFile` field is not valid because:", SourceLine(_doc, "dockerFile", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `dockerFile` field is not valid because:", SourceLine(_doc, "dockerFile", str), [e], detailed_message=f"the `dockerFile` field with value `{val}` " "is not valid because:", ) ) dockerImport = None if "dockerImport" in _doc: try: dockerImport = load_field( _doc.get("dockerImport"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("dockerImport") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `dockerImport`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("dockerImport") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `dockerImport` field is not valid because:", SourceLine(_doc, "dockerImport", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `dockerImport` field is not valid because:", SourceLine(_doc, "dockerImport", str), [e], detailed_message=f"the `dockerImport` field with value `{val}` " "is not valid because:", ) ) dockerImageId = None if "dockerImageId" in _doc: try: dockerImageId = load_field( _doc.get("dockerImageId"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("dockerImageId") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `dockerImageId`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("dockerImageId") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `dockerImageId` field is not valid because:", SourceLine(_doc, "dockerImageId", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `dockerImageId` field is not valid because:", SourceLine(_doc, "dockerImageId", str), [e], detailed_message=f"the `dockerImageId` field with value `{val}` " "is not valid because:", ) ) dockerOutputDirectory = None if "dockerOutputDirectory" in _doc: try: dockerOutputDirectory = load_field( _doc.get("dockerOutputDirectory"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("dockerOutputDirectory") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `dockerOutputDirectory`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("dockerOutputDirectory") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `dockerOutputDirectory` field is not valid because:", SourceLine(_doc, "dockerOutputDirectory", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `dockerOutputDirectory` field is not valid because:", SourceLine(_doc, "dockerOutputDirectory", str), [e], detailed_message=f"the `dockerOutputDirectory` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `class`, `dockerPull`, `dockerLoad`, `dockerFile`, `dockerImport`, `dockerImageId`, `dockerOutputDirectory`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( dockerPull=dockerPull, dockerLoad=dockerLoad, dockerFile=dockerFile, dockerImport=dockerImport, dockerImageId=dockerImageId, dockerOutputDirectory=dockerOutputDirectory, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.class_ is not None: uri = self.loadingOptions.vocab[self.class_] if p := self.loadingOptions.rvocab.get(uri[: -len(self.class_)]): uri = f"{p}:{self.class_}" else: uri = self.class_ u = save_relative_uri(uri, base_url, False, None, relative_uris) r["class"] = u if self.dockerPull is not None: r["dockerPull"] = save( self.dockerPull, top=False, base_url=base_url, relative_uris=relative_uris, ) if self.dockerLoad is not None: r["dockerLoad"] = save( self.dockerLoad, top=False, base_url=base_url, relative_uris=relative_uris, ) if self.dockerFile is not None: r["dockerFile"] = save( self.dockerFile, top=False, base_url=base_url, relative_uris=relative_uris, ) if self.dockerImport is not None: r["dockerImport"] = save( self.dockerImport, top=False, base_url=base_url, relative_uris=relative_uris, ) if self.dockerImageId is not None: r["dockerImageId"] = save( self.dockerImageId, top=False, base_url=base_url, relative_uris=relative_uris, ) if self.dockerOutputDirectory is not None: r["dockerOutputDirectory"] = save( self.dockerOutputDirectory, top=False, base_url=base_url, relative_uris=relative_uris, ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset( [ "class", "dockerPull", "dockerLoad", "dockerFile", "dockerImport", "dockerImageId", "dockerOutputDirectory", ] ) class SoftwareRequirement(ProcessRequirement): """ A list of software packages that should be configured in the environment of the defined process. """ def __init__( self, packages: Any, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.class_ = "SoftwareRequirement" self.packages = packages def __eq__(self, other: Any) -> bool: if isinstance(other, SoftwareRequirement): return bool(self.class_ == other.class_ and self.packages == other.packages) return False def __hash__(self) -> int: return hash((self.class_, self.packages)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "SoftwareRequirement": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("class") is None: raise ValidationException("missing required field `class`", None, []) class_ = load_field( _doc.get("class"), uri_SoftwareRequirement_classLoader_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("class") ) if class_ not in (cls.__name__, loadingOptions.vocab.get(cls.__name__)): raise ValidationException(f"tried `{cls.__name__}` but") except ValidationException as e: raise e try: if _doc.get("packages") is None: raise ValidationException("missing required field `packages`", None, []) packages = load_field( _doc.get("packages"), idmap_packages_array_of_SoftwarePackageLoader, baseuri, loadingOptions, lc=_doc.get("packages") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `packages`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("packages") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `packages` field is not valid because:", SourceLine(_doc, "packages", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `packages` field is not valid because:", SourceLine(_doc, "packages", str), [e], detailed_message=f"the `packages` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `class`, `packages`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( packages=packages, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.class_ is not None: uri = self.loadingOptions.vocab[self.class_] if p := self.loadingOptions.rvocab.get(uri[: -len(self.class_)]): uri = f"{p}:{self.class_}" else: uri = self.class_ u = save_relative_uri(uri, base_url, False, None, relative_uris) r["class"] = u if self.packages is not None: r["packages"] = save( self.packages, top=False, base_url=base_url, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["class", "packages"]) class SoftwarePackage(Saveable): def __init__( self, package: Any, version: Optional[Any] = None, specs: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.package = package self.version = version self.specs = specs def __eq__(self, other: Any) -> bool: if isinstance(other, SoftwarePackage): return bool( self.package == other.package and self.version == other.version and self.specs == other.specs ) return False def __hash__(self) -> int: return hash((self.package, self.version, self.specs)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "SoftwarePackage": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("package") is None: raise ValidationException("missing required field `package`", None, []) package = load_field( _doc.get("package"), strtype, baseuri, loadingOptions, lc=_doc.get("package") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `package`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("package") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `package` field is not valid because:", SourceLine(_doc, "package", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `package` field is not valid because:", SourceLine(_doc, "package", str), [e], detailed_message=f"the `package` field with value `{val}` " "is not valid because:", ) ) version = None if "version" in _doc: try: version = load_field( _doc.get("version"), union_of_None_type_or_array_of_strtype, baseuri, loadingOptions, lc=_doc.get("version") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `version`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("version") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `version` field is not valid because:", SourceLine(_doc, "version", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `version` field is not valid because:", SourceLine(_doc, "version", str), [e], detailed_message=f"the `version` field with value `{val}` " "is not valid because:", ) ) specs = None if "specs" in _doc: try: specs = load_field( _doc.get("specs"), uri_union_of_None_type_or_array_of_strtype_False_False_None_True, baseuri, loadingOptions, lc=_doc.get("specs") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `specs`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("specs") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `specs` field is not valid because:", SourceLine(_doc, "specs", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `specs` field is not valid because:", SourceLine(_doc, "specs", str), [e], detailed_message=f"the `specs` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `package`, `version`, `specs`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( package=package, version=version, specs=specs, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.package is not None: r["package"] = save( self.package, top=False, base_url=base_url, relative_uris=relative_uris ) if self.version is not None: r["version"] = save( self.version, top=False, base_url=base_url, relative_uris=relative_uris ) if self.specs is not None: u = save_relative_uri(self.specs, base_url, False, None, relative_uris) r["specs"] = u # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["package", "version", "specs"]) class Dirent(Saveable): """ Define a file or subdirectory that must be placed in the designated output directory prior to executing the command line tool. May be the result of executing an expression, such as building a configuration file from a template. """ def __init__( self, entry: Any, entryname: Optional[Any] = None, writable: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.entryname = entryname self.entry = entry self.writable = writable def __eq__(self, other: Any) -> bool: if isinstance(other, Dirent): return bool( self.entryname == other.entryname and self.entry == other.entry and self.writable == other.writable ) return False def __hash__(self) -> int: return hash((self.entryname, self.entry, self.writable)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "Dirent": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] entryname = None if "entryname" in _doc: try: entryname = load_field( _doc.get("entryname"), union_of_None_type_or_strtype_or_ExpressionLoader, baseuri, loadingOptions, lc=_doc.get("entryname") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `entryname`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("entryname") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `entryname` field is not valid because:", SourceLine(_doc, "entryname", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `entryname` field is not valid because:", SourceLine(_doc, "entryname", str), [e], detailed_message=f"the `entryname` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("entry") is None: raise ValidationException("missing required field `entry`", None, []) entry = load_field( _doc.get("entry"), union_of_strtype_or_ExpressionLoader, baseuri, loadingOptions, lc=_doc.get("entry") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `entry`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("entry") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `entry` field is not valid because:", SourceLine(_doc, "entry", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `entry` field is not valid because:", SourceLine(_doc, "entry", str), [e], detailed_message=f"the `entry` field with value `{val}` " "is not valid because:", ) ) writable = None if "writable" in _doc: try: writable = load_field( _doc.get("writable"), union_of_None_type_or_booltype, baseuri, loadingOptions, lc=_doc.get("writable") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `writable`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("writable") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `writable` field is not valid because:", SourceLine(_doc, "writable", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `writable` field is not valid because:", SourceLine(_doc, "writable", str), [e], detailed_message=f"the `writable` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `entryname`, `entry`, `writable`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( entryname=entryname, entry=entry, writable=writable, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.entryname is not None: r["entryname"] = save( self.entryname, top=False, base_url=base_url, relative_uris=relative_uris, ) if self.entry is not None: r["entry"] = save( self.entry, top=False, base_url=base_url, relative_uris=relative_uris ) if self.writable is not None: r["writable"] = save( self.writable, top=False, base_url=base_url, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["entryname", "entry", "writable"]) class InitialWorkDirRequirement(ProcessRequirement): """ Define a list of files and subdirectories that must be created by the workflow platform in the designated output directory prior to executing the command line tool. """ def __init__( self, listing: Any, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.class_ = "InitialWorkDirRequirement" self.listing = listing def __eq__(self, other: Any) -> bool: if isinstance(other, InitialWorkDirRequirement): return bool(self.class_ == other.class_ and self.listing == other.listing) return False def __hash__(self) -> int: return hash((self.class_, self.listing)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "InitialWorkDirRequirement": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("class") is None: raise ValidationException("missing required field `class`", None, []) class_ = load_field( _doc.get("class"), uri_InitialWorkDirRequirement_classLoader_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("class") ) if class_ not in (cls.__name__, loadingOptions.vocab.get(cls.__name__)): raise ValidationException(f"tried `{cls.__name__}` but") except ValidationException as e: raise e try: if _doc.get("listing") is None: raise ValidationException("missing required field `listing`", None, []) listing = load_field( _doc.get("listing"), union_of_array_of_union_of_None_type_or_FileLoader_or_array_of_union_of_FileLoader_or_DirectoryLoader_or_DirectoryLoader_or_DirentLoader_or_ExpressionLoader_or_ExpressionLoader, baseuri, loadingOptions, lc=_doc.get("listing") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `listing`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("listing") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `listing` field is not valid because:", SourceLine(_doc, "listing", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `listing` field is not valid because:", SourceLine(_doc, "listing", str), [e], detailed_message=f"the `listing` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `class`, `listing`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( listing=listing, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.class_ is not None: uri = self.loadingOptions.vocab[self.class_] if p := self.loadingOptions.rvocab.get(uri[: -len(self.class_)]): uri = f"{p}:{self.class_}" else: uri = self.class_ u = save_relative_uri(uri, base_url, False, None, relative_uris) r["class"] = u if self.listing is not None: r["listing"] = save( self.listing, top=False, base_url=base_url, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["class", "listing"]) class EnvVarRequirement(ProcessRequirement): """ Define a list of environment variables which will be set in the execution environment of the tool. See `EnvironmentDef` for details. """ def __init__( self, envDef: Any, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.class_ = "EnvVarRequirement" self.envDef = envDef def __eq__(self, other: Any) -> bool: if isinstance(other, EnvVarRequirement): return bool(self.class_ == other.class_ and self.envDef == other.envDef) return False def __hash__(self) -> int: return hash((self.class_, self.envDef)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "EnvVarRequirement": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("class") is None: raise ValidationException("missing required field `class`", None, []) class_ = load_field( _doc.get("class"), uri_EnvVarRequirement_classLoader_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("class") ) if class_ not in (cls.__name__, loadingOptions.vocab.get(cls.__name__)): raise ValidationException(f"tried `{cls.__name__}` but") except ValidationException as e: raise e try: if _doc.get("envDef") is None: raise ValidationException("missing required field `envDef`", None, []) envDef = load_field( _doc.get("envDef"), idmap_envDef_array_of_EnvironmentDefLoader, baseuri, loadingOptions, lc=_doc.get("envDef") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `envDef`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("envDef") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `envDef` field is not valid because:", SourceLine(_doc, "envDef", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `envDef` field is not valid because:", SourceLine(_doc, "envDef", str), [e], detailed_message=f"the `envDef` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `class`, `envDef`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( envDef=envDef, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.class_ is not None: uri = self.loadingOptions.vocab[self.class_] if p := self.loadingOptions.rvocab.get(uri[: -len(self.class_)]): uri = f"{p}:{self.class_}" else: uri = self.class_ u = save_relative_uri(uri, base_url, False, None, relative_uris) r["class"] = u if self.envDef is not None: r["envDef"] = save( self.envDef, top=False, base_url=base_url, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["class", "envDef"]) class ShellCommandRequirement(ProcessRequirement): """ Modify the behavior of CommandLineTool to generate a single string containing a shell command line. Each item in the argument list must be joined into a string separated by single spaces and quoted to prevent intepretation by the shell, unless `CommandLineBinding` for that argument contains `shellQuote: false`. If `shellQuote: false` is specified, the argument is joined into the command string without quoting, which allows the use of shell metacharacters such as `|` for pipes. """ def __init__( self, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.class_ = "ShellCommandRequirement" def __eq__(self, other: Any) -> bool: if isinstance(other, ShellCommandRequirement): return bool(self.class_ == other.class_) return False def __hash__(self) -> int: return hash((self.class_)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "ShellCommandRequirement": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("class") is None: raise ValidationException("missing required field `class`", None, []) class_ = load_field( _doc.get("class"), uri_ShellCommandRequirement_classLoader_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("class") ) if class_ not in (cls.__name__, loadingOptions.vocab.get(cls.__name__)): raise ValidationException(f"tried `{cls.__name__}` but") except ValidationException as e: raise e extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `class`".format(k), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.class_ is not None: uri = self.loadingOptions.vocab[self.class_] if p := self.loadingOptions.rvocab.get(uri[: -len(self.class_)]): uri = f"{p}:{self.class_}" else: uri = self.class_ u = save_relative_uri(uri, base_url, False, None, relative_uris) r["class"] = u # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["class"]) class ResourceRequirement(ProcessRequirement): """ Specify basic hardware resource requirements. "min" is the minimum amount of a resource that must be reserved to schedule a job. If "min" cannot be satisfied, the job should not be run. "max" is the maximum amount of a resource that the job shall be permitted to use. If a node has sufficient resources, multiple jobs may be scheduled on a single node provided each job's "max" resource requirements are met. If a job attempts to exceed its "max" resource allocation, an implementation may deny additional resources, which may result in job failure. If "min" is specified but "max" is not, then "max" == "min" If "max" is specified by "min" is not, then "min" == "max". It is an error if max < min. It is an error if the value of any of these fields is negative. If neither "min" nor "max" is specified for a resource, use the default values below. """ def __init__( self, coresMin: Optional[Any] = None, coresMax: Optional[Any] = None, ramMin: Optional[Any] = None, ramMax: Optional[Any] = None, tmpdirMin: Optional[Any] = None, tmpdirMax: Optional[Any] = None, outdirMin: Optional[Any] = None, outdirMax: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.class_ = "ResourceRequirement" self.coresMin = coresMin self.coresMax = coresMax self.ramMin = ramMin self.ramMax = ramMax self.tmpdirMin = tmpdirMin self.tmpdirMax = tmpdirMax self.outdirMin = outdirMin self.outdirMax = outdirMax def __eq__(self, other: Any) -> bool: if isinstance(other, ResourceRequirement): return bool( self.class_ == other.class_ and self.coresMin == other.coresMin and self.coresMax == other.coresMax and self.ramMin == other.ramMin and self.ramMax == other.ramMax and self.tmpdirMin == other.tmpdirMin and self.tmpdirMax == other.tmpdirMax and self.outdirMin == other.outdirMin and self.outdirMax == other.outdirMax ) return False def __hash__(self) -> int: return hash( ( self.class_, self.coresMin, self.coresMax, self.ramMin, self.ramMax, self.tmpdirMin, self.tmpdirMax, self.outdirMin, self.outdirMax, ) ) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "ResourceRequirement": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("class") is None: raise ValidationException("missing required field `class`", None, []) class_ = load_field( _doc.get("class"), uri_ResourceRequirement_classLoader_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("class") ) if class_ not in (cls.__name__, loadingOptions.vocab.get(cls.__name__)): raise ValidationException(f"tried `{cls.__name__}` but") except ValidationException as e: raise e coresMin = None if "coresMin" in _doc: try: coresMin = load_field( _doc.get("coresMin"), union_of_None_type_or_inttype_or_ExpressionLoader, baseuri, loadingOptions, lc=_doc.get("coresMin") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `coresMin`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("coresMin") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `coresMin` field is not valid because:", SourceLine(_doc, "coresMin", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `coresMin` field is not valid because:", SourceLine(_doc, "coresMin", str), [e], detailed_message=f"the `coresMin` field with value `{val}` " "is not valid because:", ) ) coresMax = None if "coresMax" in _doc: try: coresMax = load_field( _doc.get("coresMax"), union_of_None_type_or_inttype_or_ExpressionLoader, baseuri, loadingOptions, lc=_doc.get("coresMax") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `coresMax`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("coresMax") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `coresMax` field is not valid because:", SourceLine(_doc, "coresMax", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `coresMax` field is not valid because:", SourceLine(_doc, "coresMax", str), [e], detailed_message=f"the `coresMax` field with value `{val}` " "is not valid because:", ) ) ramMin = None if "ramMin" in _doc: try: ramMin = load_field( _doc.get("ramMin"), union_of_None_type_or_inttype_or_ExpressionLoader, baseuri, loadingOptions, lc=_doc.get("ramMin") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `ramMin`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("ramMin") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `ramMin` field is not valid because:", SourceLine(_doc, "ramMin", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `ramMin` field is not valid because:", SourceLine(_doc, "ramMin", str), [e], detailed_message=f"the `ramMin` field with value `{val}` " "is not valid because:", ) ) ramMax = None if "ramMax" in _doc: try: ramMax = load_field( _doc.get("ramMax"), union_of_None_type_or_inttype_or_ExpressionLoader, baseuri, loadingOptions, lc=_doc.get("ramMax") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `ramMax`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("ramMax") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `ramMax` field is not valid because:", SourceLine(_doc, "ramMax", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `ramMax` field is not valid because:", SourceLine(_doc, "ramMax", str), [e], detailed_message=f"the `ramMax` field with value `{val}` " "is not valid because:", ) ) tmpdirMin = None if "tmpdirMin" in _doc: try: tmpdirMin = load_field( _doc.get("tmpdirMin"), union_of_None_type_or_inttype_or_ExpressionLoader, baseuri, loadingOptions, lc=_doc.get("tmpdirMin") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `tmpdirMin`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("tmpdirMin") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `tmpdirMin` field is not valid because:", SourceLine(_doc, "tmpdirMin", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `tmpdirMin` field is not valid because:", SourceLine(_doc, "tmpdirMin", str), [e], detailed_message=f"the `tmpdirMin` field with value `{val}` " "is not valid because:", ) ) tmpdirMax = None if "tmpdirMax" in _doc: try: tmpdirMax = load_field( _doc.get("tmpdirMax"), union_of_None_type_or_inttype_or_ExpressionLoader, baseuri, loadingOptions, lc=_doc.get("tmpdirMax") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `tmpdirMax`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("tmpdirMax") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `tmpdirMax` field is not valid because:", SourceLine(_doc, "tmpdirMax", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `tmpdirMax` field is not valid because:", SourceLine(_doc, "tmpdirMax", str), [e], detailed_message=f"the `tmpdirMax` field with value `{val}` " "is not valid because:", ) ) outdirMin = None if "outdirMin" in _doc: try: outdirMin = load_field( _doc.get("outdirMin"), union_of_None_type_or_inttype_or_ExpressionLoader, baseuri, loadingOptions, lc=_doc.get("outdirMin") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `outdirMin`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("outdirMin") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `outdirMin` field is not valid because:", SourceLine(_doc, "outdirMin", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `outdirMin` field is not valid because:", SourceLine(_doc, "outdirMin", str), [e], detailed_message=f"the `outdirMin` field with value `{val}` " "is not valid because:", ) ) outdirMax = None if "outdirMax" in _doc: try: outdirMax = load_field( _doc.get("outdirMax"), union_of_None_type_or_inttype_or_ExpressionLoader, baseuri, loadingOptions, lc=_doc.get("outdirMax") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `outdirMax`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("outdirMax") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `outdirMax` field is not valid because:", SourceLine(_doc, "outdirMax", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `outdirMax` field is not valid because:", SourceLine(_doc, "outdirMax", str), [e], detailed_message=f"the `outdirMax` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `class`, `coresMin`, `coresMax`, `ramMin`, `ramMax`, `tmpdirMin`, `tmpdirMax`, `outdirMin`, `outdirMax`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( coresMin=coresMin, coresMax=coresMax, ramMin=ramMin, ramMax=ramMax, tmpdirMin=tmpdirMin, tmpdirMax=tmpdirMax, outdirMin=outdirMin, outdirMax=outdirMax, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.class_ is not None: uri = self.loadingOptions.vocab[self.class_] if p := self.loadingOptions.rvocab.get(uri[: -len(self.class_)]): uri = f"{p}:{self.class_}" else: uri = self.class_ u = save_relative_uri(uri, base_url, False, None, relative_uris) r["class"] = u if self.coresMin is not None: r["coresMin"] = save( self.coresMin, top=False, base_url=base_url, relative_uris=relative_uris ) if self.coresMax is not None: r["coresMax"] = save( self.coresMax, top=False, base_url=base_url, relative_uris=relative_uris ) if self.ramMin is not None: r["ramMin"] = save( self.ramMin, top=False, base_url=base_url, relative_uris=relative_uris ) if self.ramMax is not None: r["ramMax"] = save( self.ramMax, top=False, base_url=base_url, relative_uris=relative_uris ) if self.tmpdirMin is not None: r["tmpdirMin"] = save( self.tmpdirMin, top=False, base_url=base_url, relative_uris=relative_uris, ) if self.tmpdirMax is not None: r["tmpdirMax"] = save( self.tmpdirMax, top=False, base_url=base_url, relative_uris=relative_uris, ) if self.outdirMin is not None: r["outdirMin"] = save( self.outdirMin, top=False, base_url=base_url, relative_uris=relative_uris, ) if self.outdirMax is not None: r["outdirMax"] = save( self.outdirMax, top=False, base_url=base_url, relative_uris=relative_uris, ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset( [ "class", "coresMin", "coresMax", "ramMin", "ramMax", "tmpdirMin", "tmpdirMax", "outdirMin", "outdirMax", ] ) class WorkReuse(ProcessRequirement): """ For implementations that support reusing output from past work (on the assumption that same code and same input produce same results), control whether to enable or disable the reuse behavior for a particular tool or step (to accomodate situations where that assumption is incorrect). A reused step is not executed but instead returns the same output as the original execution. If `enableReuse` is not specified, correct tools should assume it is enabled by default. """ def __init__( self, enableReuse: Any, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.class_ = "WorkReuse" self.enableReuse = enableReuse def __eq__(self, other: Any) -> bool: if isinstance(other, WorkReuse): return bool( self.class_ == other.class_ and self.enableReuse == other.enableReuse ) return False def __hash__(self) -> int: return hash((self.class_, self.enableReuse)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "WorkReuse": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("class") is None: raise ValidationException("missing required field `class`", None, []) class_ = load_field( _doc.get("class"), uri_WorkReuse_classLoader_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("class") ) if class_ not in (cls.__name__, loadingOptions.vocab.get(cls.__name__)): raise ValidationException(f"tried `{cls.__name__}` but") except ValidationException as e: raise e try: if _doc.get("enableReuse") is None: raise ValidationException("missing required field `enableReuse`", None, []) enableReuse = load_field( _doc.get("enableReuse"), union_of_booltype_or_ExpressionLoader, baseuri, loadingOptions, lc=_doc.get("enableReuse") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `enableReuse`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("enableReuse") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `enableReuse` field is not valid because:", SourceLine(_doc, "enableReuse", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `enableReuse` field is not valid because:", SourceLine(_doc, "enableReuse", str), [e], detailed_message=f"the `enableReuse` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `class`, `enableReuse`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( enableReuse=enableReuse, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.class_ is not None: uri = self.loadingOptions.vocab[self.class_] if p := self.loadingOptions.rvocab.get(uri[: -len(self.class_)]): uri = f"{p}:{self.class_}" else: uri = self.class_ u = save_relative_uri(uri, base_url, False, None, relative_uris) r["class"] = u if self.enableReuse is not None: r["enableReuse"] = save( self.enableReuse, top=False, base_url=base_url, relative_uris=relative_uris, ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["class", "enableReuse"]) class NetworkAccess(ProcessRequirement): """ Indicate whether a process requires outgoing IPv4/IPv6 network access. Choice of IPv4 or IPv6 is implementation and site specific, correct tools must support both. If `networkAccess` is false or not specified, tools must not assume network access, except for localhost (the loopback device). If `networkAccess` is true, the tool must be able to make outgoing connections to network resources. Resources may be on a private subnet or the public Internet. However, implementations and sites may apply their own security policies to restrict what is accessible by the tool. Enabling network access does not imply a publically routable IP address or the ability to accept inbound connections. """ def __init__( self, networkAccess: Any, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.class_ = "NetworkAccess" self.networkAccess = networkAccess def __eq__(self, other: Any) -> bool: if isinstance(other, NetworkAccess): return bool( self.class_ == other.class_ and self.networkAccess == other.networkAccess ) return False def __hash__(self) -> int: return hash((self.class_, self.networkAccess)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "NetworkAccess": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("class") is None: raise ValidationException("missing required field `class`", None, []) class_ = load_field( _doc.get("class"), uri_NetworkAccess_classLoader_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("class") ) if class_ not in (cls.__name__, loadingOptions.vocab.get(cls.__name__)): raise ValidationException(f"tried `{cls.__name__}` but") except ValidationException as e: raise e try: if _doc.get("networkAccess") is None: raise ValidationException("missing required field `networkAccess`", None, []) networkAccess = load_field( _doc.get("networkAccess"), union_of_booltype_or_ExpressionLoader, baseuri, loadingOptions, lc=_doc.get("networkAccess") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `networkAccess`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("networkAccess") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `networkAccess` field is not valid because:", SourceLine(_doc, "networkAccess", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `networkAccess` field is not valid because:", SourceLine(_doc, "networkAccess", str), [e], detailed_message=f"the `networkAccess` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `class`, `networkAccess`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( networkAccess=networkAccess, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.class_ is not None: uri = self.loadingOptions.vocab[self.class_] if p := self.loadingOptions.rvocab.get(uri[: -len(self.class_)]): uri = f"{p}:{self.class_}" else: uri = self.class_ u = save_relative_uri(uri, base_url, False, None, relative_uris) r["class"] = u if self.networkAccess is not None: r["networkAccess"] = save( self.networkAccess, top=False, base_url=base_url, relative_uris=relative_uris, ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["class", "networkAccess"]) class InplaceUpdateRequirement(ProcessRequirement): """ If `inplaceUpdate` is true, then an implementation supporting this feature may permit tools to directly update files with `writable: true` in InitialWorkDirRequirement. That is, as an optimization, files may be destructively modified in place as opposed to copied and updated. An implementation must ensure that only one workflow step may access a writable file at a time. It is an error if a file which is writable by one workflow step file is accessed (for reading or writing) by any other workflow step running independently. However, a file which has been updated in a previous completed step may be used as input to multiple steps, provided it is read-only in every step. Workflow steps which modify a file must produce the modified file as output. Downstream steps which futher process the file must use the output of previous steps, and not refer to a common input (this is necessary for both ordering and correctness). Workflow authors should provide this in the `hints` section. The intent of this feature is that workflows produce the same results whether or not InplaceUpdateRequirement is supported by the implementation, and this feature is primarily available as an optimization for particular environments. Users and implementers should be aware that workflows that destructively modify inputs may not be repeatable or reproducible. In particular, enabling this feature implies that WorkReuse should not be enabled. """ def __init__( self, inplaceUpdate: Any, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.class_ = "InplaceUpdateRequirement" self.inplaceUpdate = inplaceUpdate def __eq__(self, other: Any) -> bool: if isinstance(other, InplaceUpdateRequirement): return bool( self.class_ == other.class_ and self.inplaceUpdate == other.inplaceUpdate ) return False def __hash__(self) -> int: return hash((self.class_, self.inplaceUpdate)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "InplaceUpdateRequirement": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("class") is None: raise ValidationException("missing required field `class`", None, []) class_ = load_field( _doc.get("class"), uri_InplaceUpdateRequirement_classLoader_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("class") ) if class_ not in (cls.__name__, loadingOptions.vocab.get(cls.__name__)): raise ValidationException(f"tried `{cls.__name__}` but") except ValidationException as e: raise e try: if _doc.get("inplaceUpdate") is None: raise ValidationException("missing required field `inplaceUpdate`", None, []) inplaceUpdate = load_field( _doc.get("inplaceUpdate"), booltype, baseuri, loadingOptions, lc=_doc.get("inplaceUpdate") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `inplaceUpdate`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("inplaceUpdate") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `inplaceUpdate` field is not valid because:", SourceLine(_doc, "inplaceUpdate", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `inplaceUpdate` field is not valid because:", SourceLine(_doc, "inplaceUpdate", str), [e], detailed_message=f"the `inplaceUpdate` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `class`, `inplaceUpdate`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( inplaceUpdate=inplaceUpdate, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.class_ is not None: uri = self.loadingOptions.vocab[self.class_] if p := self.loadingOptions.rvocab.get(uri[: -len(self.class_)]): uri = f"{p}:{self.class_}" else: uri = self.class_ u = save_relative_uri(uri, base_url, False, None, relative_uris) r["class"] = u if self.inplaceUpdate is not None: r["inplaceUpdate"] = save( self.inplaceUpdate, top=False, base_url=base_url, relative_uris=relative_uris, ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["class", "inplaceUpdate"]) class ToolTimeLimit(ProcessRequirement): """ Set an upper limit on the execution time of a CommandLineTool. A CommandLineTool whose execution duration exceeds the time limit may be preemptively terminated and considered failed. May also be used by batch systems to make scheduling decisions. The execution duration excludes external operations, such as staging of files, pulling a docker image etc, and only counts wall-time for the execution of the command line itself. """ def __init__( self, timelimit: Any, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.class_ = "ToolTimeLimit" self.timelimit = timelimit def __eq__(self, other: Any) -> bool: if isinstance(other, ToolTimeLimit): return bool( self.class_ == other.class_ and self.timelimit == other.timelimit ) return False def __hash__(self) -> int: return hash((self.class_, self.timelimit)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "ToolTimeLimit": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("class") is None: raise ValidationException("missing required field `class`", None, []) class_ = load_field( _doc.get("class"), uri_ToolTimeLimit_classLoader_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("class") ) if class_ not in (cls.__name__, loadingOptions.vocab.get(cls.__name__)): raise ValidationException(f"tried `{cls.__name__}` but") except ValidationException as e: raise e try: if _doc.get("timelimit") is None: raise ValidationException("missing required field `timelimit`", None, []) timelimit = load_field( _doc.get("timelimit"), union_of_inttype_or_ExpressionLoader, baseuri, loadingOptions, lc=_doc.get("timelimit") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `timelimit`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("timelimit") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `timelimit` field is not valid because:", SourceLine(_doc, "timelimit", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `timelimit` field is not valid because:", SourceLine(_doc, "timelimit", str), [e], detailed_message=f"the `timelimit` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `class`, `timelimit`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( timelimit=timelimit, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.class_ is not None: uri = self.loadingOptions.vocab[self.class_] if p := self.loadingOptions.rvocab.get(uri[: -len(self.class_)]): uri = f"{p}:{self.class_}" else: uri = self.class_ u = save_relative_uri(uri, base_url, False, None, relative_uris) r["class"] = u if self.timelimit is not None: r["timelimit"] = save( self.timelimit, top=False, base_url=base_url, relative_uris=relative_uris, ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["class", "timelimit"]) class ExpressionToolOutputParameter(OutputParameter): id: str def __init__( self, id: Any, type_: Any, label: Optional[Any] = None, secondaryFiles: Optional[Any] = None, streamable: Optional[Any] = None, doc: Optional[Any] = None, format: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.label = label self.secondaryFiles = secondaryFiles self.streamable = streamable self.doc = doc self.id = id if id is not None else "_:" + str(_uuid__.uuid4()) self.format = format self.type_ = type_ def __eq__(self, other: Any) -> bool: if isinstance(other, ExpressionToolOutputParameter): return bool( self.label == other.label and self.secondaryFiles == other.secondaryFiles and self.streamable == other.streamable and self.doc == other.doc and self.id == other.id and self.format == other.format and self.type_ == other.type_ ) return False def __hash__(self) -> int: return hash( ( self.label, self.secondaryFiles, self.streamable, self.doc, self.id, self.format, self.type_, ) ) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "ExpressionToolOutputParameter": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] id = None if "id" in _doc: try: id = load_field( _doc.get("id"), uri_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("id") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `id`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("id") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `id` field is not valid because:", SourceLine(_doc, "id", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `id` field is not valid because:", SourceLine(_doc, "id", str), [e], detailed_message=f"the `id` field with value `{val}` " "is not valid because:", ) ) __original_id_is_none = id is None if id is None: if docRoot is not None: id = docRoot else: _errors__.append(ValidationException("missing id")) if not __original_id_is_none: baseuri = cast(str, id) label = None if "label" in _doc: try: label = load_field( _doc.get("label"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("label") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `label`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("label") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [e], detailed_message=f"the `label` field with value `{val}` " "is not valid because:", ) ) secondaryFiles = None if "secondaryFiles" in _doc: try: secondaryFiles = load_field( _doc.get("secondaryFiles"), secondaryfilesdsl_union_of_None_type_or_SecondaryFileSchemaLoader_or_array_of_SecondaryFileSchemaLoader, baseuri, loadingOptions, lc=_doc.get("secondaryFiles") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `secondaryFiles`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("secondaryFiles") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `secondaryFiles` field is not valid because:", SourceLine(_doc, "secondaryFiles", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `secondaryFiles` field is not valid because:", SourceLine(_doc, "secondaryFiles", str), [e], detailed_message=f"the `secondaryFiles` field with value `{val}` " "is not valid because:", ) ) streamable = None if "streamable" in _doc: try: streamable = load_field( _doc.get("streamable"), union_of_None_type_or_booltype, baseuri, loadingOptions, lc=_doc.get("streamable") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `streamable`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("streamable") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `streamable` field is not valid because:", SourceLine(_doc, "streamable", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `streamable` field is not valid because:", SourceLine(_doc, "streamable", str), [e], detailed_message=f"the `streamable` field with value `{val}` " "is not valid because:", ) ) doc = None if "doc" in _doc: try: doc = load_field( _doc.get("doc"), union_of_None_type_or_strtype_or_array_of_strtype, baseuri, loadingOptions, lc=_doc.get("doc") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `doc`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("doc") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [e], detailed_message=f"the `doc` field with value `{val}` " "is not valid because:", ) ) format = None if "format" in _doc: try: format = load_field( _doc.get("format"), uri_union_of_None_type_or_strtype_or_ExpressionLoader_True_False_None_True, baseuri, loadingOptions, lc=_doc.get("format") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `format`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("format") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `format` field is not valid because:", SourceLine(_doc, "format", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `format` field is not valid because:", SourceLine(_doc, "format", str), [e], detailed_message=f"the `format` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("type") is None: raise ValidationException("missing required field `type`", None, []) type_ = load_field( _doc.get("type"), typedsl_union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype_2, baseuri, loadingOptions, lc=_doc.get("type") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `type`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("type") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [e], detailed_message=f"the `type` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `label`, `secondaryFiles`, `streamable`, `doc`, `id`, `format`, `type`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( label=label, secondaryFiles=secondaryFiles, streamable=streamable, doc=doc, id=id, format=format, type_=type_, extension_fields=extension_fields, loadingOptions=loadingOptions, ) loadingOptions.idx[cast(str, id)] = (_constructed, loadingOptions) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.id is not None: u = save_relative_uri(self.id, base_url, True, None, relative_uris) r["id"] = u if self.label is not None: r["label"] = save( self.label, top=False, base_url=self.id, relative_uris=relative_uris ) if self.secondaryFiles is not None: r["secondaryFiles"] = save( self.secondaryFiles, top=False, base_url=self.id, relative_uris=relative_uris, ) if self.streamable is not None: r["streamable"] = save( self.streamable, top=False, base_url=self.id, relative_uris=relative_uris, ) if self.doc is not None: r["doc"] = save( self.doc, top=False, base_url=self.id, relative_uris=relative_uris ) if self.format is not None: u = save_relative_uri(self.format, self.id, True, None, relative_uris) r["format"] = u if self.type_ is not None: r["type"] = save( self.type_, top=False, base_url=self.id, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset( ["label", "secondaryFiles", "streamable", "doc", "id", "format", "type"] ) class WorkflowInputParameter(InputParameter): id: str def __init__( self, id: Any, type_: Any, label: Optional[Any] = None, secondaryFiles: Optional[Any] = None, streamable: Optional[Any] = None, doc: Optional[Any] = None, format: Optional[Any] = None, loadContents: Optional[Any] = None, loadListing: Optional[Any] = None, default: Optional[Any] = None, inputBinding: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.label = label self.secondaryFiles = secondaryFiles self.streamable = streamable self.doc = doc self.id = id if id is not None else "_:" + str(_uuid__.uuid4()) self.format = format self.loadContents = loadContents self.loadListing = loadListing self.default = default self.type_ = type_ self.inputBinding = inputBinding def __eq__(self, other: Any) -> bool: if isinstance(other, WorkflowInputParameter): return bool( self.label == other.label and self.secondaryFiles == other.secondaryFiles and self.streamable == other.streamable and self.doc == other.doc and self.id == other.id and self.format == other.format and self.loadContents == other.loadContents and self.loadListing == other.loadListing and self.default == other.default and self.type_ == other.type_ and self.inputBinding == other.inputBinding ) return False def __hash__(self) -> int: return hash( ( self.label, self.secondaryFiles, self.streamable, self.doc, self.id, self.format, self.loadContents, self.loadListing, self.default, self.type_, self.inputBinding, ) ) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "WorkflowInputParameter": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] id = None if "id" in _doc: try: id = load_field( _doc.get("id"), uri_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("id") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `id`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("id") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `id` field is not valid because:", SourceLine(_doc, "id", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `id` field is not valid because:", SourceLine(_doc, "id", str), [e], detailed_message=f"the `id` field with value `{val}` " "is not valid because:", ) ) __original_id_is_none = id is None if id is None: if docRoot is not None: id = docRoot else: _errors__.append(ValidationException("missing id")) if not __original_id_is_none: baseuri = cast(str, id) label = None if "label" in _doc: try: label = load_field( _doc.get("label"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("label") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `label`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("label") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [e], detailed_message=f"the `label` field with value `{val}` " "is not valid because:", ) ) secondaryFiles = None if "secondaryFiles" in _doc: try: secondaryFiles = load_field( _doc.get("secondaryFiles"), secondaryfilesdsl_union_of_None_type_or_SecondaryFileSchemaLoader_or_array_of_SecondaryFileSchemaLoader, baseuri, loadingOptions, lc=_doc.get("secondaryFiles") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `secondaryFiles`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("secondaryFiles") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `secondaryFiles` field is not valid because:", SourceLine(_doc, "secondaryFiles", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `secondaryFiles` field is not valid because:", SourceLine(_doc, "secondaryFiles", str), [e], detailed_message=f"the `secondaryFiles` field with value `{val}` " "is not valid because:", ) ) streamable = None if "streamable" in _doc: try: streamable = load_field( _doc.get("streamable"), union_of_None_type_or_booltype, baseuri, loadingOptions, lc=_doc.get("streamable") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `streamable`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("streamable") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `streamable` field is not valid because:", SourceLine(_doc, "streamable", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `streamable` field is not valid because:", SourceLine(_doc, "streamable", str), [e], detailed_message=f"the `streamable` field with value `{val}` " "is not valid because:", ) ) doc = None if "doc" in _doc: try: doc = load_field( _doc.get("doc"), union_of_None_type_or_strtype_or_array_of_strtype, baseuri, loadingOptions, lc=_doc.get("doc") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `doc`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("doc") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [e], detailed_message=f"the `doc` field with value `{val}` " "is not valid because:", ) ) format = None if "format" in _doc: try: format = load_field( _doc.get("format"), uri_union_of_None_type_or_strtype_or_array_of_strtype_or_ExpressionLoader_True_False_None_True, baseuri, loadingOptions, lc=_doc.get("format") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `format`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("format") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `format` field is not valid because:", SourceLine(_doc, "format", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `format` field is not valid because:", SourceLine(_doc, "format", str), [e], detailed_message=f"the `format` field with value `{val}` " "is not valid because:", ) ) loadContents = None if "loadContents" in _doc: try: loadContents = load_field( _doc.get("loadContents"), union_of_None_type_or_booltype, baseuri, loadingOptions, lc=_doc.get("loadContents") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `loadContents`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("loadContents") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `loadContents` field is not valid because:", SourceLine(_doc, "loadContents", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `loadContents` field is not valid because:", SourceLine(_doc, "loadContents", str), [e], detailed_message=f"the `loadContents` field with value `{val}` " "is not valid because:", ) ) loadListing = None if "loadListing" in _doc: try: loadListing = load_field( _doc.get("loadListing"), union_of_None_type_or_LoadListingEnumLoader, baseuri, loadingOptions, lc=_doc.get("loadListing") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `loadListing`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("loadListing") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `loadListing` field is not valid because:", SourceLine(_doc, "loadListing", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `loadListing` field is not valid because:", SourceLine(_doc, "loadListing", str), [e], detailed_message=f"the `loadListing` field with value `{val}` " "is not valid because:", ) ) default = None if "default" in _doc: try: default = load_field( _doc.get("default"), union_of_None_type_or_CWLObjectTypeLoader, baseuri, loadingOptions, lc=_doc.get("default") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `default`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("default") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `default` field is not valid because:", SourceLine(_doc, "default", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `default` field is not valid because:", SourceLine(_doc, "default", str), [e], detailed_message=f"the `default` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("type") is None: raise ValidationException("missing required field `type`", None, []) type_ = load_field( _doc.get("type"), typedsl_union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype_2, baseuri, loadingOptions, lc=_doc.get("type") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `type`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("type") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [e], detailed_message=f"the `type` field with value `{val}` " "is not valid because:", ) ) inputBinding = None if "inputBinding" in _doc: try: inputBinding = load_field( _doc.get("inputBinding"), union_of_None_type_or_InputBindingLoader, baseuri, loadingOptions, lc=_doc.get("inputBinding") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `inputBinding`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("inputBinding") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `inputBinding` field is not valid because:", SourceLine(_doc, "inputBinding", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `inputBinding` field is not valid because:", SourceLine(_doc, "inputBinding", str), [e], detailed_message=f"the `inputBinding` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `label`, `secondaryFiles`, `streamable`, `doc`, `id`, `format`, `loadContents`, `loadListing`, `default`, `type`, `inputBinding`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( label=label, secondaryFiles=secondaryFiles, streamable=streamable, doc=doc, id=id, format=format, loadContents=loadContents, loadListing=loadListing, default=default, type_=type_, inputBinding=inputBinding, extension_fields=extension_fields, loadingOptions=loadingOptions, ) loadingOptions.idx[cast(str, id)] = (_constructed, loadingOptions) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.id is not None: u = save_relative_uri(self.id, base_url, True, None, relative_uris) r["id"] = u if self.label is not None: r["label"] = save( self.label, top=False, base_url=self.id, relative_uris=relative_uris ) if self.secondaryFiles is not None: r["secondaryFiles"] = save( self.secondaryFiles, top=False, base_url=self.id, relative_uris=relative_uris, ) if self.streamable is not None: r["streamable"] = save( self.streamable, top=False, base_url=self.id, relative_uris=relative_uris, ) if self.doc is not None: r["doc"] = save( self.doc, top=False, base_url=self.id, relative_uris=relative_uris ) if self.format is not None: u = save_relative_uri(self.format, self.id, True, None, relative_uris) r["format"] = u if self.loadContents is not None: r["loadContents"] = save( self.loadContents, top=False, base_url=self.id, relative_uris=relative_uris, ) if self.loadListing is not None: r["loadListing"] = save( self.loadListing, top=False, base_url=self.id, relative_uris=relative_uris, ) if self.default is not None: r["default"] = save( self.default, top=False, base_url=self.id, relative_uris=relative_uris ) if self.type_ is not None: r["type"] = save( self.type_, top=False, base_url=self.id, relative_uris=relative_uris ) if self.inputBinding is not None: r["inputBinding"] = save( self.inputBinding, top=False, base_url=self.id, relative_uris=relative_uris, ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset( [ "label", "secondaryFiles", "streamable", "doc", "id", "format", "loadContents", "loadListing", "default", "type", "inputBinding", ] ) class ExpressionTool(Process): """ An ExpressionTool is a type of Process object that can be run by itself or as a Workflow step. It executes a pure Javascript expression that has access to the same input parameters as a workflow. It is meant to be used sparingly as a way to isolate complex Javascript expressions that need to operate on input data and produce some result; perhaps just a rearrangement of the inputs. No Docker software container is required or allowed. """ id: str def __init__( self, inputs: Any, outputs: Any, expression: Any, id: Optional[Any] = None, label: Optional[Any] = None, doc: Optional[Any] = None, requirements: Optional[Any] = None, hints: Optional[Any] = None, cwlVersion: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.id = id if id is not None else "_:" + str(_uuid__.uuid4()) self.label = label self.doc = doc self.inputs = inputs self.outputs = outputs self.requirements = requirements self.hints = hints self.cwlVersion = cwlVersion self.class_ = "ExpressionTool" self.expression = expression def __eq__(self, other: Any) -> bool: if isinstance(other, ExpressionTool): return bool( self.id == other.id and self.label == other.label and self.doc == other.doc and self.inputs == other.inputs and self.outputs == other.outputs and self.requirements == other.requirements and self.hints == other.hints and self.cwlVersion == other.cwlVersion and self.class_ == other.class_ and self.expression == other.expression ) return False def __hash__(self) -> int: return hash( ( self.id, self.label, self.doc, self.inputs, self.outputs, self.requirements, self.hints, self.cwlVersion, self.class_, self.expression, ) ) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "ExpressionTool": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] id = None if "id" in _doc: try: id = load_field( _doc.get("id"), uri_union_of_None_type_or_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("id") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `id`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("id") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `id` field is not valid because:", SourceLine(_doc, "id", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `id` field is not valid because:", SourceLine(_doc, "id", str), [e], detailed_message=f"the `id` field with value `{val}` " "is not valid because:", ) ) __original_id_is_none = id is None if id is None: if docRoot is not None: id = docRoot else: id = "_:" + str(_uuid__.uuid4()) if not __original_id_is_none: baseuri = cast(str, id) try: if _doc.get("class") is None: raise ValidationException("missing required field `class`", None, []) class_ = load_field( _doc.get("class"), uri_ExpressionTool_classLoader_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("class") ) if class_ not in (cls.__name__, loadingOptions.vocab.get(cls.__name__)): raise ValidationException(f"tried `{cls.__name__}` but") except ValidationException as e: raise e label = None if "label" in _doc: try: label = load_field( _doc.get("label"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("label") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `label`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("label") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [e], detailed_message=f"the `label` field with value `{val}` " "is not valid because:", ) ) doc = None if "doc" in _doc: try: doc = load_field( _doc.get("doc"), union_of_None_type_or_strtype_or_array_of_strtype, baseuri, loadingOptions, lc=_doc.get("doc") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `doc`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("doc") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [e], detailed_message=f"the `doc` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("inputs") is None: raise ValidationException("missing required field `inputs`", None, []) inputs = load_field( _doc.get("inputs"), idmap_inputs_array_of_WorkflowInputParameterLoader, baseuri, loadingOptions, lc=_doc.get("inputs") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `inputs`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("inputs") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `inputs` field is not valid because:", SourceLine(_doc, "inputs", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `inputs` field is not valid because:", SourceLine(_doc, "inputs", str), [e], detailed_message=f"the `inputs` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("outputs") is None: raise ValidationException("missing required field `outputs`", None, []) outputs = load_field( _doc.get("outputs"), idmap_outputs_array_of_ExpressionToolOutputParameterLoader, baseuri, loadingOptions, lc=_doc.get("outputs") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `outputs`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("outputs") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `outputs` field is not valid because:", SourceLine(_doc, "outputs", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `outputs` field is not valid because:", SourceLine(_doc, "outputs", str), [e], detailed_message=f"the `outputs` field with value `{val}` " "is not valid because:", ) ) requirements = None if "requirements" in _doc: try: requirements = load_field( _doc.get("requirements"), idmap_requirements_union_of_None_type_or_array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_LoadListingRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_WorkReuseLoader_or_NetworkAccessLoader_or_InplaceUpdateRequirementLoader_or_ToolTimeLimitLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader_or_SecretsLoader_or_MPIRequirementLoader_or_CUDARequirementLoader_or_ShmSizeLoader, baseuri, loadingOptions, lc=_doc.get("requirements") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `requirements`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("requirements") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `requirements` field is not valid because:", SourceLine(_doc, "requirements", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `requirements` field is not valid because:", SourceLine(_doc, "requirements", str), [e], detailed_message=f"the `requirements` field with value `{val}` " "is not valid because:", ) ) hints = None if "hints" in _doc: try: hints = load_field( _doc.get("hints"), idmap_hints_union_of_None_type_or_array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_LoadListingRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_WorkReuseLoader_or_NetworkAccessLoader_or_InplaceUpdateRequirementLoader_or_ToolTimeLimitLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader_or_SecretsLoader_or_MPIRequirementLoader_or_CUDARequirementLoader_or_ShmSizeLoader_or_Any_type, baseuri, loadingOptions, lc=_doc.get("hints") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `hints`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("hints") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `hints` field is not valid because:", SourceLine(_doc, "hints", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `hints` field is not valid because:", SourceLine(_doc, "hints", str), [e], detailed_message=f"the `hints` field with value `{val}` " "is not valid because:", ) ) cwlVersion = None if "cwlVersion" in _doc: try: cwlVersion = load_field( _doc.get("cwlVersion"), uri_union_of_None_type_or_CWLVersionLoader_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("cwlVersion") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `cwlVersion`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("cwlVersion") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `cwlVersion` field is not valid because:", SourceLine(_doc, "cwlVersion", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `cwlVersion` field is not valid because:", SourceLine(_doc, "cwlVersion", str), [e], detailed_message=f"the `cwlVersion` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("expression") is None: raise ValidationException("missing required field `expression`", None, []) expression = load_field( _doc.get("expression"), ExpressionLoader, baseuri, loadingOptions, lc=_doc.get("expression") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `expression`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("expression") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `expression` field is not valid because:", SourceLine(_doc, "expression", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `expression` field is not valid because:", SourceLine(_doc, "expression", str), [e], detailed_message=f"the `expression` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `id`, `label`, `doc`, `inputs`, `outputs`, `requirements`, `hints`, `cwlVersion`, `class`, `expression`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( id=id, label=label, doc=doc, inputs=inputs, outputs=outputs, requirements=requirements, hints=hints, cwlVersion=cwlVersion, expression=expression, extension_fields=extension_fields, loadingOptions=loadingOptions, ) loadingOptions.idx[cast(str, id)] = (_constructed, loadingOptions) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.id is not None: u = save_relative_uri(self.id, base_url, True, None, relative_uris) r["id"] = u if self.class_ is not None: uri = self.loadingOptions.vocab[self.class_] if p := self.loadingOptions.rvocab.get(uri[: -len(self.class_)]): uri = f"{p}:{self.class_}" else: uri = self.class_ u = save_relative_uri(uri, self.id, False, None, relative_uris) r["class"] = u if self.label is not None: r["label"] = save( self.label, top=False, base_url=self.id, relative_uris=relative_uris ) if self.doc is not None: r["doc"] = save( self.doc, top=False, base_url=self.id, relative_uris=relative_uris ) if self.inputs is not None: r["inputs"] = save( self.inputs, top=False, base_url=self.id, relative_uris=relative_uris ) if self.outputs is not None: r["outputs"] = save( self.outputs, top=False, base_url=self.id, relative_uris=relative_uris ) if self.requirements is not None: r["requirements"] = save( self.requirements, top=False, base_url=self.id, relative_uris=relative_uris, ) if self.hints is not None: r["hints"] = save( self.hints, top=False, base_url=self.id, relative_uris=relative_uris ) if self.cwlVersion is not None: u = save_relative_uri(self.cwlVersion, self.id, False, None, relative_uris) r["cwlVersion"] = u if self.expression is not None: r["expression"] = save( self.expression, top=False, base_url=self.id, relative_uris=relative_uris, ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset( [ "id", "label", "doc", "inputs", "outputs", "requirements", "hints", "cwlVersion", "class", "expression", ] ) class WorkflowOutputParameter(OutputParameter): """ Describe an output parameter of a workflow. The parameter must be connected to one or more parameters defined in the workflow that will provide the value of the output parameter. It is legal to connect a WorkflowInputParameter to a WorkflowOutputParameter. """ id: str def __init__( self, id: Any, type_: Any, label: Optional[Any] = None, secondaryFiles: Optional[Any] = None, streamable: Optional[Any] = None, doc: Optional[Any] = None, format: Optional[Any] = None, outputSource: Optional[Any] = None, linkMerge: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.label = label self.secondaryFiles = secondaryFiles self.streamable = streamable self.doc = doc self.id = id if id is not None else "_:" + str(_uuid__.uuid4()) self.format = format self.outputSource = outputSource self.linkMerge = linkMerge self.type_ = type_ def __eq__(self, other: Any) -> bool: if isinstance(other, WorkflowOutputParameter): return bool( self.label == other.label and self.secondaryFiles == other.secondaryFiles and self.streamable == other.streamable and self.doc == other.doc and self.id == other.id and self.format == other.format and self.outputSource == other.outputSource and self.linkMerge == other.linkMerge and self.type_ == other.type_ ) return False def __hash__(self) -> int: return hash( ( self.label, self.secondaryFiles, self.streamable, self.doc, self.id, self.format, self.outputSource, self.linkMerge, self.type_, ) ) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "WorkflowOutputParameter": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] id = None if "id" in _doc: try: id = load_field( _doc.get("id"), uri_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("id") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `id`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("id") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `id` field is not valid because:", SourceLine(_doc, "id", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `id` field is not valid because:", SourceLine(_doc, "id", str), [e], detailed_message=f"the `id` field with value `{val}` " "is not valid because:", ) ) __original_id_is_none = id is None if id is None: if docRoot is not None: id = docRoot else: _errors__.append(ValidationException("missing id")) if not __original_id_is_none: baseuri = cast(str, id) label = None if "label" in _doc: try: label = load_field( _doc.get("label"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("label") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `label`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("label") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [e], detailed_message=f"the `label` field with value `{val}` " "is not valid because:", ) ) secondaryFiles = None if "secondaryFiles" in _doc: try: secondaryFiles = load_field( _doc.get("secondaryFiles"), secondaryfilesdsl_union_of_None_type_or_SecondaryFileSchemaLoader_or_array_of_SecondaryFileSchemaLoader, baseuri, loadingOptions, lc=_doc.get("secondaryFiles") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `secondaryFiles`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("secondaryFiles") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `secondaryFiles` field is not valid because:", SourceLine(_doc, "secondaryFiles", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `secondaryFiles` field is not valid because:", SourceLine(_doc, "secondaryFiles", str), [e], detailed_message=f"the `secondaryFiles` field with value `{val}` " "is not valid because:", ) ) streamable = None if "streamable" in _doc: try: streamable = load_field( _doc.get("streamable"), union_of_None_type_or_booltype, baseuri, loadingOptions, lc=_doc.get("streamable") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `streamable`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("streamable") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `streamable` field is not valid because:", SourceLine(_doc, "streamable", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `streamable` field is not valid because:", SourceLine(_doc, "streamable", str), [e], detailed_message=f"the `streamable` field with value `{val}` " "is not valid because:", ) ) doc = None if "doc" in _doc: try: doc = load_field( _doc.get("doc"), union_of_None_type_or_strtype_or_array_of_strtype, baseuri, loadingOptions, lc=_doc.get("doc") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `doc`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("doc") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [e], detailed_message=f"the `doc` field with value `{val}` " "is not valid because:", ) ) format = None if "format" in _doc: try: format = load_field( _doc.get("format"), uri_union_of_None_type_or_strtype_or_ExpressionLoader_True_False_None_True, baseuri, loadingOptions, lc=_doc.get("format") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `format`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("format") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `format` field is not valid because:", SourceLine(_doc, "format", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `format` field is not valid because:", SourceLine(_doc, "format", str), [e], detailed_message=f"the `format` field with value `{val}` " "is not valid because:", ) ) outputSource = None if "outputSource" in _doc: try: outputSource = load_field( _doc.get("outputSource"), uri_union_of_None_type_or_strtype_or_array_of_strtype_False_False_1_None, baseuri, loadingOptions, lc=_doc.get("outputSource") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `outputSource`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("outputSource") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `outputSource` field is not valid because:", SourceLine(_doc, "outputSource", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `outputSource` field is not valid because:", SourceLine(_doc, "outputSource", str), [e], detailed_message=f"the `outputSource` field with value `{val}` " "is not valid because:", ) ) linkMerge = None if "linkMerge" in _doc: try: linkMerge = load_field( _doc.get("linkMerge"), union_of_None_type_or_LinkMergeMethodLoader, baseuri, loadingOptions, lc=_doc.get("linkMerge") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `linkMerge`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("linkMerge") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `linkMerge` field is not valid because:", SourceLine(_doc, "linkMerge", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `linkMerge` field is not valid because:", SourceLine(_doc, "linkMerge", str), [e], detailed_message=f"the `linkMerge` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("type") is None: raise ValidationException("missing required field `type`", None, []) type_ = load_field( _doc.get("type"), typedsl_union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype_2, baseuri, loadingOptions, lc=_doc.get("type") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `type`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("type") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [e], detailed_message=f"the `type` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `label`, `secondaryFiles`, `streamable`, `doc`, `id`, `format`, `outputSource`, `linkMerge`, `type`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( label=label, secondaryFiles=secondaryFiles, streamable=streamable, doc=doc, id=id, format=format, outputSource=outputSource, linkMerge=linkMerge, type_=type_, extension_fields=extension_fields, loadingOptions=loadingOptions, ) loadingOptions.idx[cast(str, id)] = (_constructed, loadingOptions) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.id is not None: u = save_relative_uri(self.id, base_url, True, None, relative_uris) r["id"] = u if self.label is not None: r["label"] = save( self.label, top=False, base_url=self.id, relative_uris=relative_uris ) if self.secondaryFiles is not None: r["secondaryFiles"] = save( self.secondaryFiles, top=False, base_url=self.id, relative_uris=relative_uris, ) if self.streamable is not None: r["streamable"] = save( self.streamable, top=False, base_url=self.id, relative_uris=relative_uris, ) if self.doc is not None: r["doc"] = save( self.doc, top=False, base_url=self.id, relative_uris=relative_uris ) if self.format is not None: u = save_relative_uri(self.format, self.id, True, None, relative_uris) r["format"] = u if self.outputSource is not None: u = save_relative_uri(self.outputSource, self.id, False, 1, relative_uris) r["outputSource"] = u if self.linkMerge is not None: r["linkMerge"] = save( self.linkMerge, top=False, base_url=self.id, relative_uris=relative_uris ) if self.type_ is not None: r["type"] = save( self.type_, top=False, base_url=self.id, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset( [ "label", "secondaryFiles", "streamable", "doc", "id", "format", "outputSource", "linkMerge", "type", ] ) class Sink(Saveable): pass class WorkflowStepInput(IdentifierRequired, Sink, LoadContents, Labeled): """ The input of a workflow step connects an upstream parameter (from the workflow inputs, or the outputs of other workflows steps) with the input parameters of the process specified by the `run` field. Only input parameters declared by the target process will be passed through at runtime to the process though additonal parameters may be specified (for use within `valueFrom` expressions for instance) - unconnected or unused parameters do not represent an error condition. ## Input object A WorkflowStepInput object must contain an `id` field in the form `#fieldname` or `#prefix/fieldname`. When the `id` field contains a slash `/` the field name consists of the characters following the final slash (the prefix portion may contain one or more slashes to indicate scope). This defines a field of the workflow step input object with the value of the `source` parameter(s). ## Merging To merge multiple inbound data links, [MultipleInputFeatureRequirement](#MultipleInputFeatureRequirement) must be specified in the workflow or workflow step requirements. If the sink parameter is an array, or named in a [workflow scatter](#WorkflowStep) operation, there may be multiple inbound data links listed in the `source` field. The values from the input links are merged depending on the method specified in the `linkMerge` field. If not specified, the default method is "merge_nested". * **merge_nested** The input must be an array consisting of exactly one entry for each input link. If "merge_nested" is specified with a single link, the value from the link must be wrapped in a single-item list. * **merge_flattened** 1. The source and sink parameters must be compatible types, or the source type must be compatible with single element from the "items" type of the destination array parameter. 2. Source parameters which are arrays are concatenated. Source parameters which are single element types are appended as single elements. """ id: str def __init__( self, id: Any, source: Optional[Any] = None, linkMerge: Optional[Any] = None, loadContents: Optional[Any] = None, loadListing: Optional[Any] = None, label: Optional[Any] = None, default: Optional[Any] = None, valueFrom: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.id = id if id is not None else "_:" + str(_uuid__.uuid4()) self.source = source self.linkMerge = linkMerge self.loadContents = loadContents self.loadListing = loadListing self.label = label self.default = default self.valueFrom = valueFrom def __eq__(self, other: Any) -> bool: if isinstance(other, WorkflowStepInput): return bool( self.id == other.id and self.source == other.source and self.linkMerge == other.linkMerge and self.loadContents == other.loadContents and self.loadListing == other.loadListing and self.label == other.label and self.default == other.default and self.valueFrom == other.valueFrom ) return False def __hash__(self) -> int: return hash( ( self.id, self.source, self.linkMerge, self.loadContents, self.loadListing, self.label, self.default, self.valueFrom, ) ) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "WorkflowStepInput": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] id = None if "id" in _doc: try: id = load_field( _doc.get("id"), uri_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("id") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `id`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("id") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `id` field is not valid because:", SourceLine(_doc, "id", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `id` field is not valid because:", SourceLine(_doc, "id", str), [e], detailed_message=f"the `id` field with value `{val}` " "is not valid because:", ) ) __original_id_is_none = id is None if id is None: if docRoot is not None: id = docRoot else: _errors__.append(ValidationException("missing id")) if not __original_id_is_none: baseuri = cast(str, id) source = None if "source" in _doc: try: source = load_field( _doc.get("source"), uri_union_of_None_type_or_strtype_or_array_of_strtype_False_False_2_None, baseuri, loadingOptions, lc=_doc.get("source") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `source`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("source") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `source` field is not valid because:", SourceLine(_doc, "source", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `source` field is not valid because:", SourceLine(_doc, "source", str), [e], detailed_message=f"the `source` field with value `{val}` " "is not valid because:", ) ) linkMerge = None if "linkMerge" in _doc: try: linkMerge = load_field( _doc.get("linkMerge"), union_of_None_type_or_LinkMergeMethodLoader, baseuri, loadingOptions, lc=_doc.get("linkMerge") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `linkMerge`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("linkMerge") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `linkMerge` field is not valid because:", SourceLine(_doc, "linkMerge", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `linkMerge` field is not valid because:", SourceLine(_doc, "linkMerge", str), [e], detailed_message=f"the `linkMerge` field with value `{val}` " "is not valid because:", ) ) loadContents = None if "loadContents" in _doc: try: loadContents = load_field( _doc.get("loadContents"), union_of_None_type_or_booltype, baseuri, loadingOptions, lc=_doc.get("loadContents") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `loadContents`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("loadContents") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `loadContents` field is not valid because:", SourceLine(_doc, "loadContents", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `loadContents` field is not valid because:", SourceLine(_doc, "loadContents", str), [e], detailed_message=f"the `loadContents` field with value `{val}` " "is not valid because:", ) ) loadListing = None if "loadListing" in _doc: try: loadListing = load_field( _doc.get("loadListing"), union_of_None_type_or_LoadListingEnumLoader, baseuri, loadingOptions, lc=_doc.get("loadListing") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `loadListing`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("loadListing") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `loadListing` field is not valid because:", SourceLine(_doc, "loadListing", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `loadListing` field is not valid because:", SourceLine(_doc, "loadListing", str), [e], detailed_message=f"the `loadListing` field with value `{val}` " "is not valid because:", ) ) label = None if "label" in _doc: try: label = load_field( _doc.get("label"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("label") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `label`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("label") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [e], detailed_message=f"the `label` field with value `{val}` " "is not valid because:", ) ) default = None if "default" in _doc: try: default = load_field( _doc.get("default"), union_of_None_type_or_CWLObjectTypeLoader, baseuri, loadingOptions, lc=_doc.get("default") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `default`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("default") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `default` field is not valid because:", SourceLine(_doc, "default", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `default` field is not valid because:", SourceLine(_doc, "default", str), [e], detailed_message=f"the `default` field with value `{val}` " "is not valid because:", ) ) valueFrom = None if "valueFrom" in _doc: try: valueFrom = load_field( _doc.get("valueFrom"), union_of_None_type_or_strtype_or_ExpressionLoader, baseuri, loadingOptions, lc=_doc.get("valueFrom") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `valueFrom`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("valueFrom") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `valueFrom` field is not valid because:", SourceLine(_doc, "valueFrom", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `valueFrom` field is not valid because:", SourceLine(_doc, "valueFrom", str), [e], detailed_message=f"the `valueFrom` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `id`, `source`, `linkMerge`, `loadContents`, `loadListing`, `label`, `default`, `valueFrom`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( id=id, source=source, linkMerge=linkMerge, loadContents=loadContents, loadListing=loadListing, label=label, default=default, valueFrom=valueFrom, extension_fields=extension_fields, loadingOptions=loadingOptions, ) loadingOptions.idx[cast(str, id)] = (_constructed, loadingOptions) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.id is not None: u = save_relative_uri(self.id, base_url, True, None, relative_uris) r["id"] = u if self.source is not None: u = save_relative_uri(self.source, self.id, False, 2, relative_uris) r["source"] = u if self.linkMerge is not None: r["linkMerge"] = save( self.linkMerge, top=False, base_url=self.id, relative_uris=relative_uris ) if self.loadContents is not None: r["loadContents"] = save( self.loadContents, top=False, base_url=self.id, relative_uris=relative_uris, ) if self.loadListing is not None: r["loadListing"] = save( self.loadListing, top=False, base_url=self.id, relative_uris=relative_uris, ) if self.label is not None: r["label"] = save( self.label, top=False, base_url=self.id, relative_uris=relative_uris ) if self.default is not None: r["default"] = save( self.default, top=False, base_url=self.id, relative_uris=relative_uris ) if self.valueFrom is not None: r["valueFrom"] = save( self.valueFrom, top=False, base_url=self.id, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset( [ "id", "source", "linkMerge", "loadContents", "loadListing", "label", "default", "valueFrom", ] ) class WorkflowStepOutput(IdentifierRequired): """ Associate an output parameter of the underlying process with a workflow parameter. The workflow parameter (given in the `id` field) be may be used as a `source` to connect with input parameters of other workflow steps, or with an output parameter of the process. A unique identifier for this workflow output parameter. This is the identifier to use in the `source` field of `WorkflowStepInput` to connect the output value to downstream parameters. """ id: str def __init__( self, id: Any, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.id = id if id is not None else "_:" + str(_uuid__.uuid4()) def __eq__(self, other: Any) -> bool: if isinstance(other, WorkflowStepOutput): return bool(self.id == other.id) return False def __hash__(self) -> int: return hash((self.id)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "WorkflowStepOutput": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] id = None if "id" in _doc: try: id = load_field( _doc.get("id"), uri_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("id") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `id`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("id") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `id` field is not valid because:", SourceLine(_doc, "id", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `id` field is not valid because:", SourceLine(_doc, "id", str), [e], detailed_message=f"the `id` field with value `{val}` " "is not valid because:", ) ) __original_id_is_none = id is None if id is None: if docRoot is not None: id = docRoot else: _errors__.append(ValidationException("missing id")) if not __original_id_is_none: baseuri = cast(str, id) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `id`".format(k), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( id=id, extension_fields=extension_fields, loadingOptions=loadingOptions, ) loadingOptions.idx[cast(str, id)] = (_constructed, loadingOptions) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.id is not None: u = save_relative_uri(self.id, base_url, True, None, relative_uris) r["id"] = u # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["id"]) class WorkflowStep(IdentifierRequired, Labeled, Documented): """ A workflow step is an executable element of a workflow. It specifies the underlying process implementation (such as `CommandLineTool` or another `Workflow`) in the `run` field and connects the input and output parameters of the underlying process to workflow parameters. # Scatter/gather To use scatter/gather, [ScatterFeatureRequirement](#ScatterFeatureRequirement) must be specified in the workflow or workflow step requirements. A "scatter" operation specifies that the associated workflow step or subworkflow should execute separately over a list of input elements. Each job making up a scatter operation is independent and may be executed concurrently. The `scatter` field specifies one or more input parameters which will be scattered. An input parameter may be listed more than once. The declared type of each input parameter is implicitly becomes an array of items of the input parameter type. If a parameter is listed more than once, it becomes a nested array. As a result, upstream parameters which are connected to scattered parameters must be arrays. All output parameter types are also implicitly wrapped in arrays. Each job in the scatter results in an entry in the output array. If any scattered parameter runtime value is an empty array, all outputs are set to empty arrays and no work is done for the step, according to applicable scattering rules. If `scatter` declares more than one input parameter, `scatterMethod` describes how to decompose the input into a discrete set of jobs. * **dotproduct** specifies that each of the input arrays are aligned and one element taken from each array to construct each job. It is an error if all input arrays are not the same length. * **nested_crossproduct** specifies the Cartesian product of the inputs, producing a job for every combination of the scattered inputs. The output must be nested arrays for each level of scattering, in the order that the input arrays are listed in the `scatter` field. * **flat_crossproduct** specifies the Cartesian product of the inputs, producing a job for every combination of the scattered inputs. The output arrays must be flattened to a single level, but otherwise listed in the order that the input arrays are listed in the `scatter` field. # Subworkflows To specify a nested workflow as part of a workflow step, [SubworkflowFeatureRequirement](#SubworkflowFeatureRequirement) must be specified in the workflow or workflow step requirements. It is a fatal error if a workflow directly or indirectly invokes itself as a subworkflow (recursive workflows are not allowed). """ id: str def __init__( self, id: Any, in_: Any, out: Any, run: Any, label: Optional[Any] = None, doc: Optional[Any] = None, requirements: Optional[Any] = None, hints: Optional[Any] = None, scatter: Optional[Any] = None, scatterMethod: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.id = id if id is not None else "_:" + str(_uuid__.uuid4()) self.label = label self.doc = doc self.in_ = in_ self.out = out self.requirements = requirements self.hints = hints self.run = run self.scatter = scatter self.scatterMethod = scatterMethod def __eq__(self, other: Any) -> bool: if isinstance(other, WorkflowStep): return bool( self.id == other.id and self.label == other.label and self.doc == other.doc and self.in_ == other.in_ and self.out == other.out and self.requirements == other.requirements and self.hints == other.hints and self.run == other.run and self.scatter == other.scatter and self.scatterMethod == other.scatterMethod ) return False def __hash__(self) -> int: return hash( ( self.id, self.label, self.doc, self.in_, self.out, self.requirements, self.hints, self.run, self.scatter, self.scatterMethod, ) ) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "WorkflowStep": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] id = None if "id" in _doc: try: id = load_field( _doc.get("id"), uri_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("id") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `id`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("id") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `id` field is not valid because:", SourceLine(_doc, "id", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `id` field is not valid because:", SourceLine(_doc, "id", str), [e], detailed_message=f"the `id` field with value `{val}` " "is not valid because:", ) ) __original_id_is_none = id is None if id is None: if docRoot is not None: id = docRoot else: _errors__.append(ValidationException("missing id")) if not __original_id_is_none: baseuri = cast(str, id) label = None if "label" in _doc: try: label = load_field( _doc.get("label"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("label") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `label`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("label") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [e], detailed_message=f"the `label` field with value `{val}` " "is not valid because:", ) ) doc = None if "doc" in _doc: try: doc = load_field( _doc.get("doc"), union_of_None_type_or_strtype_or_array_of_strtype, baseuri, loadingOptions, lc=_doc.get("doc") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `doc`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("doc") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [e], detailed_message=f"the `doc` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("in") is None: raise ValidationException("missing required field `in`", None, []) in_ = load_field( _doc.get("in"), idmap_in__array_of_WorkflowStepInputLoader, baseuri, loadingOptions, lc=_doc.get("in") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `in`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("in") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `in` field is not valid because:", SourceLine(_doc, "in", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `in` field is not valid because:", SourceLine(_doc, "in", str), [e], detailed_message=f"the `in` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("out") is None: raise ValidationException("missing required field `out`", None, []) out = load_field( _doc.get("out"), uri_union_of_array_of_union_of_strtype_or_WorkflowStepOutputLoader_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("out") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `out`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("out") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `out` field is not valid because:", SourceLine(_doc, "out", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `out` field is not valid because:", SourceLine(_doc, "out", str), [e], detailed_message=f"the `out` field with value `{val}` " "is not valid because:", ) ) requirements = None if "requirements" in _doc: try: requirements = load_field( _doc.get("requirements"), idmap_requirements_union_of_None_type_or_array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_LoadListingRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_WorkReuseLoader_or_NetworkAccessLoader_or_InplaceUpdateRequirementLoader_or_ToolTimeLimitLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader_or_SecretsLoader_or_MPIRequirementLoader_or_CUDARequirementLoader_or_ShmSizeLoader, baseuri, loadingOptions, lc=_doc.get("requirements") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `requirements`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("requirements") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `requirements` field is not valid because:", SourceLine(_doc, "requirements", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `requirements` field is not valid because:", SourceLine(_doc, "requirements", str), [e], detailed_message=f"the `requirements` field with value `{val}` " "is not valid because:", ) ) hints = None if "hints" in _doc: try: hints = load_field( _doc.get("hints"), idmap_hints_union_of_None_type_or_array_of_Any_type, baseuri, loadingOptions, lc=_doc.get("hints") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `hints`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("hints") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `hints` field is not valid because:", SourceLine(_doc, "hints", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `hints` field is not valid because:", SourceLine(_doc, "hints", str), [e], detailed_message=f"the `hints` field with value `{val}` " "is not valid because:", ) ) subscope_baseuri = expand_url('run', baseuri, loadingOptions, True) try: if _doc.get("run") is None: raise ValidationException("missing required field `run`", None, []) run = load_field( _doc.get("run"), uri_union_of_strtype_or_CommandLineToolLoader_or_ExpressionToolLoader_or_WorkflowLoader_or_ProcessGeneratorLoader_False_False_None_None, subscope_baseuri, loadingOptions, lc=_doc.get("run") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `run`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("run") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `run` field is not valid because:", SourceLine(_doc, "run", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `run` field is not valid because:", SourceLine(_doc, "run", str), [e], detailed_message=f"the `run` field with value `{val}` " "is not valid because:", ) ) scatter = None if "scatter" in _doc: try: scatter = load_field( _doc.get("scatter"), uri_union_of_None_type_or_strtype_or_array_of_strtype_False_False_0_None, baseuri, loadingOptions, lc=_doc.get("scatter") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `scatter`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("scatter") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `scatter` field is not valid because:", SourceLine(_doc, "scatter", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `scatter` field is not valid because:", SourceLine(_doc, "scatter", str), [e], detailed_message=f"the `scatter` field with value `{val}` " "is not valid because:", ) ) scatterMethod = None if "scatterMethod" in _doc: try: scatterMethod = load_field( _doc.get("scatterMethod"), uri_union_of_None_type_or_ScatterMethodLoader_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("scatterMethod") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `scatterMethod`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("scatterMethod") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `scatterMethod` field is not valid because:", SourceLine(_doc, "scatterMethod", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `scatterMethod` field is not valid because:", SourceLine(_doc, "scatterMethod", str), [e], detailed_message=f"the `scatterMethod` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `id`, `label`, `doc`, `in`, `out`, `requirements`, `hints`, `run`, `scatter`, `scatterMethod`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( id=id, label=label, doc=doc, in_=in_, out=out, requirements=requirements, hints=hints, run=run, scatter=scatter, scatterMethod=scatterMethod, extension_fields=extension_fields, loadingOptions=loadingOptions, ) loadingOptions.idx[cast(str, id)] = (_constructed, loadingOptions) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.id is not None: u = save_relative_uri(self.id, base_url, True, None, relative_uris) r["id"] = u if self.label is not None: r["label"] = save( self.label, top=False, base_url=self.id, relative_uris=relative_uris ) if self.doc is not None: r["doc"] = save( self.doc, top=False, base_url=self.id, relative_uris=relative_uris ) if self.in_ is not None: r["in"] = save( self.in_, top=False, base_url=self.id, relative_uris=relative_uris ) if self.out is not None: u = save_relative_uri(self.out, self.id, True, None, relative_uris) r["out"] = u if self.requirements is not None: r["requirements"] = save( self.requirements, top=False, base_url=self.id, relative_uris=relative_uris, ) if self.hints is not None: r["hints"] = save( self.hints, top=False, base_url=self.id, relative_uris=relative_uris ) if self.run is not None: u = save_relative_uri(self.run, self.id, False, None, relative_uris) r["run"] = u if self.scatter is not None: u = save_relative_uri(self.scatter, self.id, False, 0, relative_uris) r["scatter"] = u if self.scatterMethod is not None: u = save_relative_uri( self.scatterMethod, self.id, False, None, relative_uris ) r["scatterMethod"] = u # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset( [ "id", "label", "doc", "in", "out", "requirements", "hints", "run", "scatter", "scatterMethod", ] ) class Workflow(Process): """ A workflow describes a set of **steps** and the **dependencies** between those steps. When a step produces output that will be consumed by a second step, the first step is a dependency of the second step. When there is a dependency, the workflow engine must execute the preceding step and wait for it to successfully produce output before executing the dependent step. If two steps are defined in the workflow graph that are not directly or indirectly dependent, these steps are **independent**, and may execute in any order or execute concurrently. A workflow is complete when all steps have been executed. Dependencies between parameters are expressed using the `source` field on [workflow step input parameters](#WorkflowStepInput) and [workflow output parameters](#WorkflowOutputParameter). The `source` field expresses the dependency of one parameter on another such that when a value is associated with the parameter specified by `source`, that value is propagated to the destination parameter. When all data links inbound to a given step are fufilled, the step is ready to execute. ## Workflow success and failure A completed step must result in one of `success`, `temporaryFailure` or `permanentFailure` states. An implementation may choose to retry a step execution which resulted in `temporaryFailure`. An implementation may choose to either continue running other steps of a workflow, or terminate immediately upon `permanentFailure`. * If any step of a workflow execution results in `permanentFailure`, then the workflow status is `permanentFailure`. * If one or more steps result in `temporaryFailure` and all other steps complete `success` or are not executed, then the workflow status is `temporaryFailure`. * If all workflow steps are executed and complete with `success`, then the workflow status is `success`. # Extensions [ScatterFeatureRequirement](#ScatterFeatureRequirement) and [SubworkflowFeatureRequirement](#SubworkflowFeatureRequirement) are available as standard [extensions](#Extensions_and_Metadata) to core workflow semantics. """ id: str def __init__( self, inputs: Any, outputs: Any, steps: Any, id: Optional[Any] = None, label: Optional[Any] = None, doc: Optional[Any] = None, requirements: Optional[Any] = None, hints: Optional[Any] = None, cwlVersion: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.id = id if id is not None else "_:" + str(_uuid__.uuid4()) self.label = label self.doc = doc self.inputs = inputs self.outputs = outputs self.requirements = requirements self.hints = hints self.cwlVersion = cwlVersion self.class_ = "Workflow" self.steps = steps def __eq__(self, other: Any) -> bool: if isinstance(other, Workflow): return bool( self.id == other.id and self.label == other.label and self.doc == other.doc and self.inputs == other.inputs and self.outputs == other.outputs and self.requirements == other.requirements and self.hints == other.hints and self.cwlVersion == other.cwlVersion and self.class_ == other.class_ and self.steps == other.steps ) return False def __hash__(self) -> int: return hash( ( self.id, self.label, self.doc, self.inputs, self.outputs, self.requirements, self.hints, self.cwlVersion, self.class_, self.steps, ) ) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "Workflow": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] id = None if "id" in _doc: try: id = load_field( _doc.get("id"), uri_union_of_None_type_or_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("id") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `id`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("id") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `id` field is not valid because:", SourceLine(_doc, "id", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `id` field is not valid because:", SourceLine(_doc, "id", str), [e], detailed_message=f"the `id` field with value `{val}` " "is not valid because:", ) ) __original_id_is_none = id is None if id is None: if docRoot is not None: id = docRoot else: id = "_:" + str(_uuid__.uuid4()) if not __original_id_is_none: baseuri = cast(str, id) try: if _doc.get("class") is None: raise ValidationException("missing required field `class`", None, []) class_ = load_field( _doc.get("class"), uri_Workflow_classLoader_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("class") ) if class_ not in (cls.__name__, loadingOptions.vocab.get(cls.__name__)): raise ValidationException(f"tried `{cls.__name__}` but") except ValidationException as e: raise e label = None if "label" in _doc: try: label = load_field( _doc.get("label"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("label") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `label`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("label") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [e], detailed_message=f"the `label` field with value `{val}` " "is not valid because:", ) ) doc = None if "doc" in _doc: try: doc = load_field( _doc.get("doc"), union_of_None_type_or_strtype_or_array_of_strtype, baseuri, loadingOptions, lc=_doc.get("doc") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `doc`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("doc") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [e], detailed_message=f"the `doc` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("inputs") is None: raise ValidationException("missing required field `inputs`", None, []) inputs = load_field( _doc.get("inputs"), idmap_inputs_array_of_WorkflowInputParameterLoader, baseuri, loadingOptions, lc=_doc.get("inputs") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `inputs`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("inputs") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `inputs` field is not valid because:", SourceLine(_doc, "inputs", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `inputs` field is not valid because:", SourceLine(_doc, "inputs", str), [e], detailed_message=f"the `inputs` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("outputs") is None: raise ValidationException("missing required field `outputs`", None, []) outputs = load_field( _doc.get("outputs"), idmap_outputs_array_of_WorkflowOutputParameterLoader, baseuri, loadingOptions, lc=_doc.get("outputs") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `outputs`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("outputs") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `outputs` field is not valid because:", SourceLine(_doc, "outputs", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `outputs` field is not valid because:", SourceLine(_doc, "outputs", str), [e], detailed_message=f"the `outputs` field with value `{val}` " "is not valid because:", ) ) requirements = None if "requirements" in _doc: try: requirements = load_field( _doc.get("requirements"), idmap_requirements_union_of_None_type_or_array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_LoadListingRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_WorkReuseLoader_or_NetworkAccessLoader_or_InplaceUpdateRequirementLoader_or_ToolTimeLimitLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader_or_SecretsLoader_or_MPIRequirementLoader_or_CUDARequirementLoader_or_ShmSizeLoader, baseuri, loadingOptions, lc=_doc.get("requirements") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `requirements`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("requirements") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `requirements` field is not valid because:", SourceLine(_doc, "requirements", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `requirements` field is not valid because:", SourceLine(_doc, "requirements", str), [e], detailed_message=f"the `requirements` field with value `{val}` " "is not valid because:", ) ) hints = None if "hints" in _doc: try: hints = load_field( _doc.get("hints"), idmap_hints_union_of_None_type_or_array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_LoadListingRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_WorkReuseLoader_or_NetworkAccessLoader_or_InplaceUpdateRequirementLoader_or_ToolTimeLimitLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader_or_SecretsLoader_or_MPIRequirementLoader_or_CUDARequirementLoader_or_ShmSizeLoader_or_Any_type, baseuri, loadingOptions, lc=_doc.get("hints") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `hints`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("hints") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `hints` field is not valid because:", SourceLine(_doc, "hints", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `hints` field is not valid because:", SourceLine(_doc, "hints", str), [e], detailed_message=f"the `hints` field with value `{val}` " "is not valid because:", ) ) cwlVersion = None if "cwlVersion" in _doc: try: cwlVersion = load_field( _doc.get("cwlVersion"), uri_union_of_None_type_or_CWLVersionLoader_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("cwlVersion") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `cwlVersion`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("cwlVersion") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `cwlVersion` field is not valid because:", SourceLine(_doc, "cwlVersion", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `cwlVersion` field is not valid because:", SourceLine(_doc, "cwlVersion", str), [e], detailed_message=f"the `cwlVersion` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("steps") is None: raise ValidationException("missing required field `steps`", None, []) steps = load_field( _doc.get("steps"), idmap_steps_union_of_array_of_WorkflowStepLoader, baseuri, loadingOptions, lc=_doc.get("steps") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `steps`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("steps") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `steps` field is not valid because:", SourceLine(_doc, "steps", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `steps` field is not valid because:", SourceLine(_doc, "steps", str), [e], detailed_message=f"the `steps` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `id`, `label`, `doc`, `inputs`, `outputs`, `requirements`, `hints`, `cwlVersion`, `class`, `steps`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( id=id, label=label, doc=doc, inputs=inputs, outputs=outputs, requirements=requirements, hints=hints, cwlVersion=cwlVersion, steps=steps, extension_fields=extension_fields, loadingOptions=loadingOptions, ) loadingOptions.idx[cast(str, id)] = (_constructed, loadingOptions) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.id is not None: u = save_relative_uri(self.id, base_url, True, None, relative_uris) r["id"] = u if self.class_ is not None: uri = self.loadingOptions.vocab[self.class_] if p := self.loadingOptions.rvocab.get(uri[: -len(self.class_)]): uri = f"{p}:{self.class_}" else: uri = self.class_ u = save_relative_uri(uri, self.id, False, None, relative_uris) r["class"] = u if self.label is not None: r["label"] = save( self.label, top=False, base_url=self.id, relative_uris=relative_uris ) if self.doc is not None: r["doc"] = save( self.doc, top=False, base_url=self.id, relative_uris=relative_uris ) if self.inputs is not None: r["inputs"] = save( self.inputs, top=False, base_url=self.id, relative_uris=relative_uris ) if self.outputs is not None: r["outputs"] = save( self.outputs, top=False, base_url=self.id, relative_uris=relative_uris ) if self.requirements is not None: r["requirements"] = save( self.requirements, top=False, base_url=self.id, relative_uris=relative_uris, ) if self.hints is not None: r["hints"] = save( self.hints, top=False, base_url=self.id, relative_uris=relative_uris ) if self.cwlVersion is not None: u = save_relative_uri(self.cwlVersion, self.id, False, None, relative_uris) r["cwlVersion"] = u if self.steps is not None: r["steps"] = save( self.steps, top=False, base_url=self.id, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset( [ "id", "label", "doc", "inputs", "outputs", "requirements", "hints", "cwlVersion", "class", "steps", ] ) class SubworkflowFeatureRequirement(ProcessRequirement): """ Indicates that the workflow platform must support nested workflows in the `run` field of [WorkflowStep](#WorkflowStep). """ def __init__( self, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.class_ = "SubworkflowFeatureRequirement" def __eq__(self, other: Any) -> bool: if isinstance(other, SubworkflowFeatureRequirement): return bool(self.class_ == other.class_) return False def __hash__(self) -> int: return hash((self.class_)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "SubworkflowFeatureRequirement": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("class") is None: raise ValidationException("missing required field `class`", None, []) class_ = load_field( _doc.get("class"), uri_SubworkflowFeatureRequirement_classLoader_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("class") ) if class_ not in (cls.__name__, loadingOptions.vocab.get(cls.__name__)): raise ValidationException(f"tried `{cls.__name__}` but") except ValidationException as e: raise e extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `class`".format(k), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.class_ is not None: uri = self.loadingOptions.vocab[self.class_] if p := self.loadingOptions.rvocab.get(uri[: -len(self.class_)]): uri = f"{p}:{self.class_}" else: uri = self.class_ u = save_relative_uri(uri, base_url, False, None, relative_uris) r["class"] = u # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["class"]) class ScatterFeatureRequirement(ProcessRequirement): """ Indicates that the workflow platform must support the `scatter` and `scatterMethod` fields of [WorkflowStep](#WorkflowStep). """ def __init__( self, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.class_ = "ScatterFeatureRequirement" def __eq__(self, other: Any) -> bool: if isinstance(other, ScatterFeatureRequirement): return bool(self.class_ == other.class_) return False def __hash__(self) -> int: return hash((self.class_)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "ScatterFeatureRequirement": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("class") is None: raise ValidationException("missing required field `class`", None, []) class_ = load_field( _doc.get("class"), uri_ScatterFeatureRequirement_classLoader_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("class") ) if class_ not in (cls.__name__, loadingOptions.vocab.get(cls.__name__)): raise ValidationException(f"tried `{cls.__name__}` but") except ValidationException as e: raise e extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `class`".format(k), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.class_ is not None: uri = self.loadingOptions.vocab[self.class_] if p := self.loadingOptions.rvocab.get(uri[: -len(self.class_)]): uri = f"{p}:{self.class_}" else: uri = self.class_ u = save_relative_uri(uri, base_url, False, None, relative_uris) r["class"] = u # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["class"]) class MultipleInputFeatureRequirement(ProcessRequirement): """ Indicates that the workflow platform must support multiple inbound data links listed in the `source` field of [WorkflowStepInput](#WorkflowStepInput). """ def __init__( self, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.class_ = "MultipleInputFeatureRequirement" def __eq__(self, other: Any) -> bool: if isinstance(other, MultipleInputFeatureRequirement): return bool(self.class_ == other.class_) return False def __hash__(self) -> int: return hash((self.class_)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "MultipleInputFeatureRequirement": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("class") is None: raise ValidationException("missing required field `class`", None, []) class_ = load_field( _doc.get("class"), uri_MultipleInputFeatureRequirement_classLoader_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("class") ) if class_ not in (cls.__name__, loadingOptions.vocab.get(cls.__name__)): raise ValidationException(f"tried `{cls.__name__}` but") except ValidationException as e: raise e extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `class`".format(k), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.class_ is not None: uri = self.loadingOptions.vocab[self.class_] if p := self.loadingOptions.rvocab.get(uri[: -len(self.class_)]): uri = f"{p}:{self.class_}" else: uri = self.class_ u = save_relative_uri(uri, base_url, False, None, relative_uris) r["class"] = u # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["class"]) class StepInputExpressionRequirement(ProcessRequirement): """ Indicate that the workflow platform must support the `valueFrom` field of [WorkflowStepInput](#WorkflowStepInput). """ def __init__( self, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.class_ = "StepInputExpressionRequirement" def __eq__(self, other: Any) -> bool: if isinstance(other, StepInputExpressionRequirement): return bool(self.class_ == other.class_) return False def __hash__(self) -> int: return hash((self.class_)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "StepInputExpressionRequirement": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("class") is None: raise ValidationException("missing required field `class`", None, []) class_ = load_field( _doc.get("class"), uri_StepInputExpressionRequirement_classLoader_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("class") ) if class_ not in (cls.__name__, loadingOptions.vocab.get(cls.__name__)): raise ValidationException(f"tried `{cls.__name__}` but") except ValidationException as e: raise e extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `class`".format(k), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.class_ is not None: uri = self.loadingOptions.vocab[self.class_] if p := self.loadingOptions.rvocab.get(uri[: -len(self.class_)]): uri = f"{p}:{self.class_}" else: uri = self.class_ u = save_relative_uri(uri, base_url, False, None, relative_uris) r["class"] = u # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["class"]) class Secrets(ProcessRequirement): def __init__( self, secrets: Any, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.class_ = "Secrets" self.secrets = secrets def __eq__(self, other: Any) -> bool: if isinstance(other, Secrets): return bool(self.class_ == other.class_ and self.secrets == other.secrets) return False def __hash__(self) -> int: return hash((self.class_, self.secrets)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "Secrets": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("class") is None: raise ValidationException("missing required field `class`", None, []) class_ = load_field( _doc.get("class"), uri_strtype_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("class") ) if class_ not in (cls.__name__, loadingOptions.vocab.get(cls.__name__)): raise ValidationException(f"tried `{cls.__name__}` but") except ValidationException as e: raise e try: if _doc.get("secrets") is None: raise ValidationException("missing required field `secrets`", None, []) secrets = load_field( _doc.get("secrets"), uri_array_of_strtype_False_False_0_None, baseuri, loadingOptions, lc=_doc.get("secrets") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `secrets`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("secrets") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `secrets` field is not valid because:", SourceLine(_doc, "secrets", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `secrets` field is not valid because:", SourceLine(_doc, "secrets", str), [e], detailed_message=f"the `secrets` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `class`, `secrets`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( secrets=secrets, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.class_ is not None: uri = self.loadingOptions.vocab[self.class_] if p := self.loadingOptions.rvocab.get(uri[: -len(self.class_)]): uri = f"{p}:{self.class_}" else: uri = self.class_ u = save_relative_uri(uri, base_url, False, None, relative_uris) r["class"] = u if self.secrets is not None: u = save_relative_uri(self.secrets, base_url, False, 0, relative_uris) r["secrets"] = u # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["class", "secrets"]) class ProcessGenerator(Process): id: str def __init__( self, inputs: Any, outputs: Any, run: Any, id: Optional[Any] = None, label: Optional[Any] = None, doc: Optional[Any] = None, requirements: Optional[Any] = None, hints: Optional[Any] = None, cwlVersion: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.id = id if id is not None else "_:" + str(_uuid__.uuid4()) self.label = label self.doc = doc self.inputs = inputs self.outputs = outputs self.requirements = requirements self.hints = hints self.cwlVersion = cwlVersion self.class_ = "ProcessGenerator" self.run = run def __eq__(self, other: Any) -> bool: if isinstance(other, ProcessGenerator): return bool( self.id == other.id and self.label == other.label and self.doc == other.doc and self.inputs == other.inputs and self.outputs == other.outputs and self.requirements == other.requirements and self.hints == other.hints and self.cwlVersion == other.cwlVersion and self.class_ == other.class_ and self.run == other.run ) return False def __hash__(self) -> int: return hash( ( self.id, self.label, self.doc, self.inputs, self.outputs, self.requirements, self.hints, self.cwlVersion, self.class_, self.run, ) ) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "ProcessGenerator": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] id = None if "id" in _doc: try: id = load_field( _doc.get("id"), uri_union_of_None_type_or_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("id") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `id`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("id") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `id` field is not valid because:", SourceLine(_doc, "id", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `id` field is not valid because:", SourceLine(_doc, "id", str), [e], detailed_message=f"the `id` field with value `{val}` " "is not valid because:", ) ) __original_id_is_none = id is None if id is None: if docRoot is not None: id = docRoot else: id = "_:" + str(_uuid__.uuid4()) if not __original_id_is_none: baseuri = cast(str, id) try: if _doc.get("class") is None: raise ValidationException("missing required field `class`", None, []) class_ = load_field( _doc.get("class"), uri_strtype_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("class") ) if class_ not in (cls.__name__, loadingOptions.vocab.get(cls.__name__)): raise ValidationException(f"tried `{cls.__name__}` but") except ValidationException as e: raise e label = None if "label" in _doc: try: label = load_field( _doc.get("label"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("label") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `label`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("label") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [e], detailed_message=f"the `label` field with value `{val}` " "is not valid because:", ) ) doc = None if "doc" in _doc: try: doc = load_field( _doc.get("doc"), union_of_None_type_or_strtype_or_array_of_strtype, baseuri, loadingOptions, lc=_doc.get("doc") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `doc`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("doc") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [e], detailed_message=f"the `doc` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("inputs") is None: raise ValidationException("missing required field `inputs`", None, []) inputs = load_field( _doc.get("inputs"), idmap_inputs_array_of_union_of_CommandInputParameterLoader_or_WorkflowInputParameterLoader, baseuri, loadingOptions, lc=_doc.get("inputs") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `inputs`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("inputs") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `inputs` field is not valid because:", SourceLine(_doc, "inputs", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `inputs` field is not valid because:", SourceLine(_doc, "inputs", str), [e], detailed_message=f"the `inputs` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("outputs") is None: raise ValidationException("missing required field `outputs`", None, []) outputs = load_field( _doc.get("outputs"), idmap_outputs_array_of_union_of_CommandOutputParameterLoader_or_ExpressionToolOutputParameterLoader_or_WorkflowOutputParameterLoader, baseuri, loadingOptions, lc=_doc.get("outputs") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `outputs`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("outputs") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `outputs` field is not valid because:", SourceLine(_doc, "outputs", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `outputs` field is not valid because:", SourceLine(_doc, "outputs", str), [e], detailed_message=f"the `outputs` field with value `{val}` " "is not valid because:", ) ) requirements = None if "requirements" in _doc: try: requirements = load_field( _doc.get("requirements"), idmap_requirements_union_of_None_type_or_array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_LoadListingRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_WorkReuseLoader_or_NetworkAccessLoader_or_InplaceUpdateRequirementLoader_or_ToolTimeLimitLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader_or_SecretsLoader_or_MPIRequirementLoader_or_CUDARequirementLoader_or_ShmSizeLoader, baseuri, loadingOptions, lc=_doc.get("requirements") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `requirements`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("requirements") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `requirements` field is not valid because:", SourceLine(_doc, "requirements", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `requirements` field is not valid because:", SourceLine(_doc, "requirements", str), [e], detailed_message=f"the `requirements` field with value `{val}` " "is not valid because:", ) ) hints = None if "hints" in _doc: try: hints = load_field( _doc.get("hints"), idmap_hints_union_of_None_type_or_array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_LoadListingRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_WorkReuseLoader_or_NetworkAccessLoader_or_InplaceUpdateRequirementLoader_or_ToolTimeLimitLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader_or_SecretsLoader_or_MPIRequirementLoader_or_CUDARequirementLoader_or_ShmSizeLoader_or_Any_type, baseuri, loadingOptions, lc=_doc.get("hints") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `hints`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("hints") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `hints` field is not valid because:", SourceLine(_doc, "hints", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `hints` field is not valid because:", SourceLine(_doc, "hints", str), [e], detailed_message=f"the `hints` field with value `{val}` " "is not valid because:", ) ) cwlVersion = None if "cwlVersion" in _doc: try: cwlVersion = load_field( _doc.get("cwlVersion"), uri_union_of_None_type_or_CWLVersionLoader_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("cwlVersion") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `cwlVersion`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("cwlVersion") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `cwlVersion` field is not valid because:", SourceLine(_doc, "cwlVersion", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `cwlVersion` field is not valid because:", SourceLine(_doc, "cwlVersion", str), [e], detailed_message=f"the `cwlVersion` field with value `{val}` " "is not valid because:", ) ) subscope_baseuri = expand_url('run', baseuri, loadingOptions, True) try: if _doc.get("run") is None: raise ValidationException("missing required field `run`", None, []) run = load_field( _doc.get("run"), uri_union_of_strtype_or_CommandLineToolLoader_or_ExpressionToolLoader_or_WorkflowLoader_or_ProcessGeneratorLoader_False_False_None_None, subscope_baseuri, loadingOptions, lc=_doc.get("run") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `run`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("run") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `run` field is not valid because:", SourceLine(_doc, "run", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `run` field is not valid because:", SourceLine(_doc, "run", str), [e], detailed_message=f"the `run` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `id`, `label`, `doc`, `inputs`, `outputs`, `requirements`, `hints`, `cwlVersion`, `class`, `run`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( id=id, label=label, doc=doc, inputs=inputs, outputs=outputs, requirements=requirements, hints=hints, cwlVersion=cwlVersion, run=run, extension_fields=extension_fields, loadingOptions=loadingOptions, ) loadingOptions.idx[cast(str, id)] = (_constructed, loadingOptions) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.id is not None: u = save_relative_uri(self.id, base_url, True, None, relative_uris) r["id"] = u if self.class_ is not None: uri = self.loadingOptions.vocab[self.class_] if p := self.loadingOptions.rvocab.get(uri[: -len(self.class_)]): uri = f"{p}:{self.class_}" else: uri = self.class_ u = save_relative_uri(uri, self.id, False, None, relative_uris) r["class"] = u if self.label is not None: r["label"] = save( self.label, top=False, base_url=self.id, relative_uris=relative_uris ) if self.doc is not None: r["doc"] = save( self.doc, top=False, base_url=self.id, relative_uris=relative_uris ) if self.inputs is not None: r["inputs"] = save( self.inputs, top=False, base_url=self.id, relative_uris=relative_uris ) if self.outputs is not None: r["outputs"] = save( self.outputs, top=False, base_url=self.id, relative_uris=relative_uris ) if self.requirements is not None: r["requirements"] = save( self.requirements, top=False, base_url=self.id, relative_uris=relative_uris, ) if self.hints is not None: r["hints"] = save( self.hints, top=False, base_url=self.id, relative_uris=relative_uris ) if self.cwlVersion is not None: u = save_relative_uri(self.cwlVersion, self.id, False, None, relative_uris) r["cwlVersion"] = u if self.run is not None: u = save_relative_uri(self.run, self.id, False, None, relative_uris) r["run"] = u # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset( [ "id", "label", "doc", "inputs", "outputs", "requirements", "hints", "cwlVersion", "class", "run", ] ) class MPIRequirement(ProcessRequirement): """ Indicates that a process requires an MPI runtime. """ def __init__( self, processes: Any, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.class_ = "MPIRequirement" self.processes = processes def __eq__(self, other: Any) -> bool: if isinstance(other, MPIRequirement): return bool( self.class_ == other.class_ and self.processes == other.processes ) return False def __hash__(self) -> int: return hash((self.class_, self.processes)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "MPIRequirement": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("class") is None: raise ValidationException("missing required field `class`", None, []) class_ = load_field( _doc.get("class"), uri_strtype_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("class") ) if class_ not in (cls.__name__, loadingOptions.vocab.get(cls.__name__)): raise ValidationException(f"tried `{cls.__name__}` but") except ValidationException as e: raise e try: if _doc.get("processes") is None: raise ValidationException("missing required field `processes`", None, []) processes = load_field( _doc.get("processes"), union_of_inttype_or_ExpressionLoader, baseuri, loadingOptions, lc=_doc.get("processes") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `processes`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("processes") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `processes` field is not valid because:", SourceLine(_doc, "processes", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `processes` field is not valid because:", SourceLine(_doc, "processes", str), [e], detailed_message=f"the `processes` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `class`, `processes`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( processes=processes, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.class_ is not None: uri = self.loadingOptions.vocab[self.class_] if p := self.loadingOptions.rvocab.get(uri[: -len(self.class_)]): uri = f"{p}:{self.class_}" else: uri = self.class_ u = save_relative_uri(uri, base_url, False, None, relative_uris) r["class"] = u if self.processes is not None: r["processes"] = save( self.processes, top=False, base_url=base_url, relative_uris=relative_uris, ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["class", "processes"]) class CUDARequirement(ProcessRequirement): """ Require support for NVIDA CUDA (GPU hardware acceleration). """ def __init__( self, cudaComputeCapability: Any, cudaVersionMin: Any, cudaDeviceCountMax: Optional[Any] = None, cudaDeviceCountMin: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.class_ = "CUDARequirement" self.cudaComputeCapability = cudaComputeCapability self.cudaDeviceCountMax = cudaDeviceCountMax self.cudaDeviceCountMin = cudaDeviceCountMin self.cudaVersionMin = cudaVersionMin def __eq__(self, other: Any) -> bool: if isinstance(other, CUDARequirement): return bool( self.class_ == other.class_ and self.cudaComputeCapability == other.cudaComputeCapability and self.cudaDeviceCountMax == other.cudaDeviceCountMax and self.cudaDeviceCountMin == other.cudaDeviceCountMin and self.cudaVersionMin == other.cudaVersionMin ) return False def __hash__(self) -> int: return hash( ( self.class_, self.cudaComputeCapability, self.cudaDeviceCountMax, self.cudaDeviceCountMin, self.cudaVersionMin, ) ) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "CUDARequirement": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("class") is None: raise ValidationException("missing required field `class`", None, []) class_ = load_field( _doc.get("class"), uri_strtype_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("class") ) if class_ not in (cls.__name__, loadingOptions.vocab.get(cls.__name__)): raise ValidationException(f"tried `{cls.__name__}` but") except ValidationException as e: raise e try: if _doc.get("cudaComputeCapability") is None: raise ValidationException("missing required field `cudaComputeCapability`", None, []) cudaComputeCapability = load_field( _doc.get("cudaComputeCapability"), union_of_strtype_or_array_of_strtype, baseuri, loadingOptions, lc=_doc.get("cudaComputeCapability") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `cudaComputeCapability`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("cudaComputeCapability") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `cudaComputeCapability` field is not valid because:", SourceLine(_doc, "cudaComputeCapability", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `cudaComputeCapability` field is not valid because:", SourceLine(_doc, "cudaComputeCapability", str), [e], detailed_message=f"the `cudaComputeCapability` field with value `{val}` " "is not valid because:", ) ) cudaDeviceCountMax = None if "cudaDeviceCountMax" in _doc: try: cudaDeviceCountMax = load_field( _doc.get("cudaDeviceCountMax"), union_of_None_type_or_inttype_or_ExpressionLoader, baseuri, loadingOptions, lc=_doc.get("cudaDeviceCountMax") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `cudaDeviceCountMax`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("cudaDeviceCountMax") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `cudaDeviceCountMax` field is not valid because:", SourceLine(_doc, "cudaDeviceCountMax", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `cudaDeviceCountMax` field is not valid because:", SourceLine(_doc, "cudaDeviceCountMax", str), [e], detailed_message=f"the `cudaDeviceCountMax` field with value `{val}` " "is not valid because:", ) ) cudaDeviceCountMin = None if "cudaDeviceCountMin" in _doc: try: cudaDeviceCountMin = load_field( _doc.get("cudaDeviceCountMin"), union_of_None_type_or_inttype_or_ExpressionLoader, baseuri, loadingOptions, lc=_doc.get("cudaDeviceCountMin") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `cudaDeviceCountMin`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("cudaDeviceCountMin") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `cudaDeviceCountMin` field is not valid because:", SourceLine(_doc, "cudaDeviceCountMin", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `cudaDeviceCountMin` field is not valid because:", SourceLine(_doc, "cudaDeviceCountMin", str), [e], detailed_message=f"the `cudaDeviceCountMin` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("cudaVersionMin") is None: raise ValidationException("missing required field `cudaVersionMin`", None, []) cudaVersionMin = load_field( _doc.get("cudaVersionMin"), strtype, baseuri, loadingOptions, lc=_doc.get("cudaVersionMin") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `cudaVersionMin`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("cudaVersionMin") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `cudaVersionMin` field is not valid because:", SourceLine(_doc, "cudaVersionMin", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `cudaVersionMin` field is not valid because:", SourceLine(_doc, "cudaVersionMin", str), [e], detailed_message=f"the `cudaVersionMin` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `class`, `cudaComputeCapability`, `cudaDeviceCountMax`, `cudaDeviceCountMin`, `cudaVersionMin`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( cudaComputeCapability=cudaComputeCapability, cudaDeviceCountMax=cudaDeviceCountMax, cudaDeviceCountMin=cudaDeviceCountMin, cudaVersionMin=cudaVersionMin, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.class_ is not None: uri = self.loadingOptions.vocab[self.class_] if p := self.loadingOptions.rvocab.get(uri[: -len(self.class_)]): uri = f"{p}:{self.class_}" else: uri = self.class_ u = save_relative_uri(uri, base_url, False, None, relative_uris) r["class"] = u if self.cudaComputeCapability is not None: r["cudaComputeCapability"] = save( self.cudaComputeCapability, top=False, base_url=base_url, relative_uris=relative_uris, ) if self.cudaDeviceCountMax is not None: r["cudaDeviceCountMax"] = save( self.cudaDeviceCountMax, top=False, base_url=base_url, relative_uris=relative_uris, ) if self.cudaDeviceCountMin is not None: r["cudaDeviceCountMin"] = save( self.cudaDeviceCountMin, top=False, base_url=base_url, relative_uris=relative_uris, ) if self.cudaVersionMin is not None: r["cudaVersionMin"] = save( self.cudaVersionMin, top=False, base_url=base_url, relative_uris=relative_uris, ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset( [ "class", "cudaComputeCapability", "cudaDeviceCountMax", "cudaDeviceCountMin", "cudaVersionMin", ] ) class ShmSize(ProcessRequirement): def __init__( self, shmSize: Any, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.class_ = "ShmSize" self.shmSize = shmSize def __eq__(self, other: Any) -> bool: if isinstance(other, ShmSize): return bool(self.class_ == other.class_ and self.shmSize == other.shmSize) return False def __hash__(self) -> int: return hash((self.class_, self.shmSize)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "ShmSize": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("class") is None: raise ValidationException("missing required field `class`", None, []) class_ = load_field( _doc.get("class"), uri_strtype_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("class") ) if class_ not in (cls.__name__, loadingOptions.vocab.get(cls.__name__)): raise ValidationException(f"tried `{cls.__name__}` but") except ValidationException as e: raise e try: if _doc.get("shmSize") is None: raise ValidationException("missing required field `shmSize`", None, []) shmSize = load_field( _doc.get("shmSize"), strtype, baseuri, loadingOptions, lc=_doc.get("shmSize") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `shmSize`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("shmSize") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `shmSize` field is not valid because:", SourceLine(_doc, "shmSize", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `shmSize` field is not valid because:", SourceLine(_doc, "shmSize", str), [e], detailed_message=f"the `shmSize` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `class`, `shmSize`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( shmSize=shmSize, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.class_ is not None: uri = self.loadingOptions.vocab[self.class_] if p := self.loadingOptions.rvocab.get(uri[: -len(self.class_)]): uri = f"{p}:{self.class_}" else: uri = self.class_ u = save_relative_uri(uri, base_url, False, None, relative_uris) r["class"] = u if self.shmSize is not None: r["shmSize"] = save( self.shmSize, top=False, base_url=base_url, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["class", "shmSize"]) _vocab = { "Any": "https://w3id.org/cwl/salad#Any", "ArraySchema": "https://w3id.org/cwl/salad#ArraySchema", "CUDARequirement": "http://commonwl.org/cwltool#CUDARequirement", "CWLArraySchema": "https://w3id.org/cwl/cwl#CWLArraySchema", "CWLInputFile": "https://w3id.org/cwl/cwl#CWLInputFile", "CWLObjectType": "https://w3id.org/cwl/cwl#CWLObjectType", "CWLRecordField": "https://w3id.org/cwl/cwl#CWLRecordField", "CWLRecordSchema": "https://w3id.org/cwl/cwl#CWLRecordSchema", "CWLType": "https://w3id.org/cwl/cwl#CWLType", "CWLVersion": "https://w3id.org/cwl/cwl#CWLVersion", "CommandInputArraySchema": "https://w3id.org/cwl/cwl#CommandInputArraySchema", "CommandInputEnumSchema": "https://w3id.org/cwl/cwl#CommandInputEnumSchema", "CommandInputParameter": "https://w3id.org/cwl/cwl#CommandInputParameter", "CommandInputRecordField": "https://w3id.org/cwl/cwl#CommandInputRecordField", "CommandInputRecordSchema": "https://w3id.org/cwl/cwl#CommandInputRecordSchema", "CommandInputSchema": "https://w3id.org/cwl/cwl#CommandInputSchema", "CommandLineBindable": "https://w3id.org/cwl/cwl#CommandLineBindable", "CommandLineBinding": "https://w3id.org/cwl/cwl#CommandLineBinding", "CommandLineTool": "https://w3id.org/cwl/cwl#CommandLineTool", "CommandOutputArraySchema": "https://w3id.org/cwl/cwl#CommandOutputArraySchema", "CommandOutputBinding": "https://w3id.org/cwl/cwl#CommandOutputBinding", "CommandOutputEnumSchema": "https://w3id.org/cwl/cwl#CommandOutputEnumSchema", "CommandOutputParameter": "https://w3id.org/cwl/cwl#CommandOutputParameter", "CommandOutputRecordField": "https://w3id.org/cwl/cwl#CommandOutputRecordField", "CommandOutputRecordSchema": "https://w3id.org/cwl/cwl#CommandOutputRecordSchema", "Directory": "https://w3id.org/cwl/cwl#Directory", "Dirent": "https://w3id.org/cwl/cwl#Dirent", "DockerRequirement": "https://w3id.org/cwl/cwl#DockerRequirement", "Documented": "https://w3id.org/cwl/salad#Documented", "EnumSchema": "https://w3id.org/cwl/salad#EnumSchema", "EnvVarRequirement": "https://w3id.org/cwl/cwl#EnvVarRequirement", "EnvironmentDef": "https://w3id.org/cwl/cwl#EnvironmentDef", "Expression": "https://w3id.org/cwl/cwl#Expression", "ExpressionPlaceholder": "https://w3id.org/cwl/cwl#ExpressionPlaceholder", "ExpressionTool": "https://w3id.org/cwl/cwl#ExpressionTool", "ExpressionToolOutputParameter": "https://w3id.org/cwl/cwl#ExpressionToolOutputParameter", "FieldBase": "https://w3id.org/cwl/cwl#FieldBase", "File": "https://w3id.org/cwl/cwl#File", "IOSchema": "https://w3id.org/cwl/cwl#IOSchema", "Identified": "https://w3id.org/cwl/cwl#Identified", "IdentifierRequired": "https://w3id.org/cwl/cwl#IdentifierRequired", "InitialWorkDirRequirement": "https://w3id.org/cwl/cwl#InitialWorkDirRequirement", "InlineJavascriptRequirement": "https://w3id.org/cwl/cwl#InlineJavascriptRequirement", "InplaceUpdateRequirement": "https://w3id.org/cwl/cwl#InplaceUpdateRequirement", "InputArraySchema": "https://w3id.org/cwl/cwl#InputArraySchema", "InputBinding": "https://w3id.org/cwl/cwl#InputBinding", "InputEnumSchema": "https://w3id.org/cwl/cwl#InputEnumSchema", "InputFormat": "https://w3id.org/cwl/cwl#InputFormat", "InputParameter": "https://w3id.org/cwl/cwl#InputParameter", "InputRecordField": "https://w3id.org/cwl/cwl#InputRecordField", "InputRecordSchema": "https://w3id.org/cwl/cwl#InputRecordSchema", "InputSchema": "https://w3id.org/cwl/cwl#InputSchema", "Labeled": "https://w3id.org/cwl/cwl#Labeled", "LinkMergeMethod": "https://w3id.org/cwl/cwl#LinkMergeMethod", "LoadContents": "https://w3id.org/cwl/cwl#LoadContents", "LoadListingEnum": "https://w3id.org/cwl/cwl#LoadListingEnum", "LoadListingRequirement": "https://w3id.org/cwl/cwl#LoadListingRequirement", "MPIRequirement": "http://commonwl.org/cwltool#MPIRequirement", "MapSchema": "https://w3id.org/cwl/salad#MapSchema", "MultipleInputFeatureRequirement": "https://w3id.org/cwl/cwl#MultipleInputFeatureRequirement", "NetworkAccess": "https://w3id.org/cwl/cwl#NetworkAccess", "OutputArraySchema": "https://w3id.org/cwl/cwl#OutputArraySchema", "OutputEnumSchema": "https://w3id.org/cwl/cwl#OutputEnumSchema", "OutputFormat": "https://w3id.org/cwl/cwl#OutputFormat", "OutputParameter": "https://w3id.org/cwl/cwl#OutputParameter", "OutputRecordField": "https://w3id.org/cwl/cwl#OutputRecordField", "OutputRecordSchema": "https://w3id.org/cwl/cwl#OutputRecordSchema", "OutputSchema": "https://w3id.org/cwl/cwl#OutputSchema", "Parameter": "https://w3id.org/cwl/cwl#Parameter", "PrimitiveType": "https://w3id.org/cwl/salad#PrimitiveType", "Process": "https://w3id.org/cwl/cwl#Process", "ProcessGenerator": "http://commonwl.org/cwltool#ProcessGenerator", "ProcessRequirement": "https://w3id.org/cwl/cwl#ProcessRequirement", "RecordField": "https://w3id.org/cwl/salad#RecordField", "RecordSchema": "https://w3id.org/cwl/salad#RecordSchema", "ResourceRequirement": "https://w3id.org/cwl/cwl#ResourceRequirement", "ScatterFeatureRequirement": "https://w3id.org/cwl/cwl#ScatterFeatureRequirement", "ScatterMethod": "https://w3id.org/cwl/cwl#ScatterMethod", "SchemaDefRequirement": "https://w3id.org/cwl/cwl#SchemaDefRequirement", "SecondaryFileSchema": "https://w3id.org/cwl/cwl#SecondaryFileSchema", "Secrets": "http://commonwl.org/cwltool#Secrets", "ShellCommandRequirement": "https://w3id.org/cwl/cwl#ShellCommandRequirement", "ShmSize": "http://commonwl.org/cwltool#ShmSize", "Sink": "https://w3id.org/cwl/cwl#Sink", "SoftwarePackage": "https://w3id.org/cwl/cwl#SoftwarePackage", "SoftwareRequirement": "https://w3id.org/cwl/cwl#SoftwareRequirement", "StepInputExpressionRequirement": "https://w3id.org/cwl/cwl#StepInputExpressionRequirement", "SubworkflowFeatureRequirement": "https://w3id.org/cwl/cwl#SubworkflowFeatureRequirement", "ToolTimeLimit": "https://w3id.org/cwl/cwl#ToolTimeLimit", "UnionSchema": "https://w3id.org/cwl/salad#UnionSchema", "WorkReuse": "https://w3id.org/cwl/cwl#WorkReuse", "Workflow": "https://w3id.org/cwl/cwl#Workflow", "WorkflowInputParameter": "https://w3id.org/cwl/cwl#WorkflowInputParameter", "WorkflowOutputParameter": "https://w3id.org/cwl/cwl#WorkflowOutputParameter", "WorkflowStep": "https://w3id.org/cwl/cwl#WorkflowStep", "WorkflowStepInput": "https://w3id.org/cwl/cwl#WorkflowStepInput", "WorkflowStepOutput": "https://w3id.org/cwl/cwl#WorkflowStepOutput", "array": "https://w3id.org/cwl/salad#array", "boolean": "http://www.w3.org/2001/XMLSchema#boolean", "deep_listing": "https://w3id.org/cwl/cwl#LoadListingEnum/deep_listing", "dotproduct": "https://w3id.org/cwl/cwl#ScatterMethod/dotproduct", "double": "http://www.w3.org/2001/XMLSchema#double", "draft-2": "https://w3id.org/cwl/cwl#draft-2", "draft-3": "https://w3id.org/cwl/cwl#draft-3", "draft-3.dev1": "https://w3id.org/cwl/cwl#draft-3.dev1", "draft-3.dev2": "https://w3id.org/cwl/cwl#draft-3.dev2", "draft-3.dev3": "https://w3id.org/cwl/cwl#draft-3.dev3", "draft-3.dev4": "https://w3id.org/cwl/cwl#draft-3.dev4", "draft-3.dev5": "https://w3id.org/cwl/cwl#draft-3.dev5", "draft-4.dev1": "https://w3id.org/cwl/cwl#draft-4.dev1", "draft-4.dev2": "https://w3id.org/cwl/cwl#draft-4.dev2", "draft-4.dev3": "https://w3id.org/cwl/cwl#draft-4.dev3", "enum": "https://w3id.org/cwl/salad#enum", "flat_crossproduct": "https://w3id.org/cwl/cwl#ScatterMethod/flat_crossproduct", "float": "http://www.w3.org/2001/XMLSchema#float", "int": "http://www.w3.org/2001/XMLSchema#int", "long": "http://www.w3.org/2001/XMLSchema#long", "map": "https://w3id.org/cwl/salad#map", "merge_flattened": "https://w3id.org/cwl/cwl#LinkMergeMethod/merge_flattened", "merge_nested": "https://w3id.org/cwl/cwl#LinkMergeMethod/merge_nested", "nested_crossproduct": "https://w3id.org/cwl/cwl#ScatterMethod/nested_crossproduct", "no_listing": "https://w3id.org/cwl/cwl#LoadListingEnum/no_listing", "null": "https://w3id.org/cwl/salad#null", "record": "https://w3id.org/cwl/salad#record", "shallow_listing": "https://w3id.org/cwl/cwl#LoadListingEnum/shallow_listing", "stderr": "https://w3id.org/cwl/cwl#stderr", "stdin": "https://w3id.org/cwl/cwl#stdin", "stdout": "https://w3id.org/cwl/cwl#stdout", "string": "http://www.w3.org/2001/XMLSchema#string", "union": "https://w3id.org/cwl/salad#union", "v1.0": "https://w3id.org/cwl/cwl#v1.0", "v1.0.dev4": "https://w3id.org/cwl/cwl#v1.0.dev4", "v1.1": "https://w3id.org/cwl/cwl#v1.1", "v1.1.0-dev1": "https://w3id.org/cwl/cwl#v1.1.0-dev1", } _rvocab = { "https://w3id.org/cwl/salad#Any": "Any", "https://w3id.org/cwl/salad#ArraySchema": "ArraySchema", "http://commonwl.org/cwltool#CUDARequirement": "CUDARequirement", "https://w3id.org/cwl/cwl#CWLArraySchema": "CWLArraySchema", "https://w3id.org/cwl/cwl#CWLInputFile": "CWLInputFile", "https://w3id.org/cwl/cwl#CWLObjectType": "CWLObjectType", "https://w3id.org/cwl/cwl#CWLRecordField": "CWLRecordField", "https://w3id.org/cwl/cwl#CWLRecordSchema": "CWLRecordSchema", "https://w3id.org/cwl/cwl#CWLType": "CWLType", "https://w3id.org/cwl/cwl#CWLVersion": "CWLVersion", "https://w3id.org/cwl/cwl#CommandInputArraySchema": "CommandInputArraySchema", "https://w3id.org/cwl/cwl#CommandInputEnumSchema": "CommandInputEnumSchema", "https://w3id.org/cwl/cwl#CommandInputParameter": "CommandInputParameter", "https://w3id.org/cwl/cwl#CommandInputRecordField": "CommandInputRecordField", "https://w3id.org/cwl/cwl#CommandInputRecordSchema": "CommandInputRecordSchema", "https://w3id.org/cwl/cwl#CommandInputSchema": "CommandInputSchema", "https://w3id.org/cwl/cwl#CommandLineBindable": "CommandLineBindable", "https://w3id.org/cwl/cwl#CommandLineBinding": "CommandLineBinding", "https://w3id.org/cwl/cwl#CommandLineTool": "CommandLineTool", "https://w3id.org/cwl/cwl#CommandOutputArraySchema": "CommandOutputArraySchema", "https://w3id.org/cwl/cwl#CommandOutputBinding": "CommandOutputBinding", "https://w3id.org/cwl/cwl#CommandOutputEnumSchema": "CommandOutputEnumSchema", "https://w3id.org/cwl/cwl#CommandOutputParameter": "CommandOutputParameter", "https://w3id.org/cwl/cwl#CommandOutputRecordField": "CommandOutputRecordField", "https://w3id.org/cwl/cwl#CommandOutputRecordSchema": "CommandOutputRecordSchema", "https://w3id.org/cwl/cwl#Directory": "Directory", "https://w3id.org/cwl/cwl#Dirent": "Dirent", "https://w3id.org/cwl/cwl#DockerRequirement": "DockerRequirement", "https://w3id.org/cwl/salad#Documented": "Documented", "https://w3id.org/cwl/salad#EnumSchema": "EnumSchema", "https://w3id.org/cwl/cwl#EnvVarRequirement": "EnvVarRequirement", "https://w3id.org/cwl/cwl#EnvironmentDef": "EnvironmentDef", "https://w3id.org/cwl/cwl#Expression": "Expression", "https://w3id.org/cwl/cwl#ExpressionPlaceholder": "ExpressionPlaceholder", "https://w3id.org/cwl/cwl#ExpressionTool": "ExpressionTool", "https://w3id.org/cwl/cwl#ExpressionToolOutputParameter": "ExpressionToolOutputParameter", "https://w3id.org/cwl/cwl#FieldBase": "FieldBase", "https://w3id.org/cwl/cwl#File": "File", "https://w3id.org/cwl/cwl#IOSchema": "IOSchema", "https://w3id.org/cwl/cwl#Identified": "Identified", "https://w3id.org/cwl/cwl#IdentifierRequired": "IdentifierRequired", "https://w3id.org/cwl/cwl#InitialWorkDirRequirement": "InitialWorkDirRequirement", "https://w3id.org/cwl/cwl#InlineJavascriptRequirement": "InlineJavascriptRequirement", "https://w3id.org/cwl/cwl#InplaceUpdateRequirement": "InplaceUpdateRequirement", "https://w3id.org/cwl/cwl#InputArraySchema": "InputArraySchema", "https://w3id.org/cwl/cwl#InputBinding": "InputBinding", "https://w3id.org/cwl/cwl#InputEnumSchema": "InputEnumSchema", "https://w3id.org/cwl/cwl#InputFormat": "InputFormat", "https://w3id.org/cwl/cwl#InputParameter": "InputParameter", "https://w3id.org/cwl/cwl#InputRecordField": "InputRecordField", "https://w3id.org/cwl/cwl#InputRecordSchema": "InputRecordSchema", "https://w3id.org/cwl/cwl#InputSchema": "InputSchema", "https://w3id.org/cwl/cwl#Labeled": "Labeled", "https://w3id.org/cwl/cwl#LinkMergeMethod": "LinkMergeMethod", "https://w3id.org/cwl/cwl#LoadContents": "LoadContents", "https://w3id.org/cwl/cwl#LoadListingEnum": "LoadListingEnum", "https://w3id.org/cwl/cwl#LoadListingRequirement": "LoadListingRequirement", "http://commonwl.org/cwltool#MPIRequirement": "MPIRequirement", "https://w3id.org/cwl/salad#MapSchema": "MapSchema", "https://w3id.org/cwl/cwl#MultipleInputFeatureRequirement": "MultipleInputFeatureRequirement", "https://w3id.org/cwl/cwl#NetworkAccess": "NetworkAccess", "https://w3id.org/cwl/cwl#OutputArraySchema": "OutputArraySchema", "https://w3id.org/cwl/cwl#OutputEnumSchema": "OutputEnumSchema", "https://w3id.org/cwl/cwl#OutputFormat": "OutputFormat", "https://w3id.org/cwl/cwl#OutputParameter": "OutputParameter", "https://w3id.org/cwl/cwl#OutputRecordField": "OutputRecordField", "https://w3id.org/cwl/cwl#OutputRecordSchema": "OutputRecordSchema", "https://w3id.org/cwl/cwl#OutputSchema": "OutputSchema", "https://w3id.org/cwl/cwl#Parameter": "Parameter", "https://w3id.org/cwl/salad#PrimitiveType": "PrimitiveType", "https://w3id.org/cwl/cwl#Process": "Process", "http://commonwl.org/cwltool#ProcessGenerator": "ProcessGenerator", "https://w3id.org/cwl/cwl#ProcessRequirement": "ProcessRequirement", "https://w3id.org/cwl/salad#RecordField": "RecordField", "https://w3id.org/cwl/salad#RecordSchema": "RecordSchema", "https://w3id.org/cwl/cwl#ResourceRequirement": "ResourceRequirement", "https://w3id.org/cwl/cwl#ScatterFeatureRequirement": "ScatterFeatureRequirement", "https://w3id.org/cwl/cwl#ScatterMethod": "ScatterMethod", "https://w3id.org/cwl/cwl#SchemaDefRequirement": "SchemaDefRequirement", "https://w3id.org/cwl/cwl#SecondaryFileSchema": "SecondaryFileSchema", "http://commonwl.org/cwltool#Secrets": "Secrets", "https://w3id.org/cwl/cwl#ShellCommandRequirement": "ShellCommandRequirement", "http://commonwl.org/cwltool#ShmSize": "ShmSize", "https://w3id.org/cwl/cwl#Sink": "Sink", "https://w3id.org/cwl/cwl#SoftwarePackage": "SoftwarePackage", "https://w3id.org/cwl/cwl#SoftwareRequirement": "SoftwareRequirement", "https://w3id.org/cwl/cwl#StepInputExpressionRequirement": "StepInputExpressionRequirement", "https://w3id.org/cwl/cwl#SubworkflowFeatureRequirement": "SubworkflowFeatureRequirement", "https://w3id.org/cwl/cwl#ToolTimeLimit": "ToolTimeLimit", "https://w3id.org/cwl/salad#UnionSchema": "UnionSchema", "https://w3id.org/cwl/cwl#WorkReuse": "WorkReuse", "https://w3id.org/cwl/cwl#Workflow": "Workflow", "https://w3id.org/cwl/cwl#WorkflowInputParameter": "WorkflowInputParameter", "https://w3id.org/cwl/cwl#WorkflowOutputParameter": "WorkflowOutputParameter", "https://w3id.org/cwl/cwl#WorkflowStep": "WorkflowStep", "https://w3id.org/cwl/cwl#WorkflowStepInput": "WorkflowStepInput", "https://w3id.org/cwl/cwl#WorkflowStepOutput": "WorkflowStepOutput", "https://w3id.org/cwl/salad#array": "array", "http://www.w3.org/2001/XMLSchema#boolean": "boolean", "https://w3id.org/cwl/cwl#LoadListingEnum/deep_listing": "deep_listing", "https://w3id.org/cwl/cwl#ScatterMethod/dotproduct": "dotproduct", "http://www.w3.org/2001/XMLSchema#double": "double", "https://w3id.org/cwl/cwl#draft-2": "draft-2", "https://w3id.org/cwl/cwl#draft-3": "draft-3", "https://w3id.org/cwl/cwl#draft-3.dev1": "draft-3.dev1", "https://w3id.org/cwl/cwl#draft-3.dev2": "draft-3.dev2", "https://w3id.org/cwl/cwl#draft-3.dev3": "draft-3.dev3", "https://w3id.org/cwl/cwl#draft-3.dev4": "draft-3.dev4", "https://w3id.org/cwl/cwl#draft-3.dev5": "draft-3.dev5", "https://w3id.org/cwl/cwl#draft-4.dev1": "draft-4.dev1", "https://w3id.org/cwl/cwl#draft-4.dev2": "draft-4.dev2", "https://w3id.org/cwl/cwl#draft-4.dev3": "draft-4.dev3", "https://w3id.org/cwl/salad#enum": "enum", "https://w3id.org/cwl/cwl#ScatterMethod/flat_crossproduct": "flat_crossproduct", "http://www.w3.org/2001/XMLSchema#float": "float", "http://www.w3.org/2001/XMLSchema#int": "int", "http://www.w3.org/2001/XMLSchema#long": "long", "https://w3id.org/cwl/salad#map": "map", "https://w3id.org/cwl/cwl#LinkMergeMethod/merge_flattened": "merge_flattened", "https://w3id.org/cwl/cwl#LinkMergeMethod/merge_nested": "merge_nested", "https://w3id.org/cwl/cwl#ScatterMethod/nested_crossproduct": "nested_crossproduct", "https://w3id.org/cwl/cwl#LoadListingEnum/no_listing": "no_listing", "https://w3id.org/cwl/salad#null": "null", "https://w3id.org/cwl/salad#record": "record", "https://w3id.org/cwl/cwl#LoadListingEnum/shallow_listing": "shallow_listing", "https://w3id.org/cwl/cwl#stderr": "stderr", "https://w3id.org/cwl/cwl#stdin": "stdin", "https://w3id.org/cwl/cwl#stdout": "stdout", "http://www.w3.org/2001/XMLSchema#string": "string", "https://w3id.org/cwl/salad#union": "union", "https://w3id.org/cwl/cwl#v1.0": "v1.0", "https://w3id.org/cwl/cwl#v1.0.dev4": "v1.0.dev4", "https://w3id.org/cwl/cwl#v1.1": "v1.1", "https://w3id.org/cwl/cwl#v1.1.0-dev1": "v1.1.0-dev1", } strtype = _PrimitiveLoader(str) inttype = _PrimitiveLoader(int) floattype = _PrimitiveLoader(float) booltype = _PrimitiveLoader(bool) None_type = _PrimitiveLoader(type(None)) Any_type = _AnyLoader() PrimitiveTypeLoader = _EnumLoader( ( "null", "boolean", "int", "long", "float", "double", "string", ), "PrimitiveType", ) """ Names of salad data types (based on Avro schema declarations). Refer to the [Avro schema declaration documentation](https://avro.apache.org/docs/current/spec.html#schemas) for detailed information. null: no value boolean: a binary value int: 32-bit signed integer long: 64-bit signed integer float: single precision (32-bit) IEEE 754 floating-point number double: double precision (64-bit) IEEE 754 floating-point number string: Unicode character sequence """ AnyLoader = _EnumLoader(("Any",), "Any") """ The **Any** type validates for any non-null value. """ RecordFieldLoader = _RecordLoader(RecordField, None, None) RecordSchemaLoader = _RecordLoader(RecordSchema, None, None) EnumSchemaLoader = _RecordLoader(EnumSchema, None, None) ArraySchemaLoader = _RecordLoader(ArraySchema, None, None) MapSchemaLoader = _RecordLoader(MapSchema, None, None) UnionSchemaLoader = _RecordLoader(UnionSchema, None, None) CWLTypeLoader = _EnumLoader( ( "null", "boolean", "int", "long", "float", "double", "string", "File", "Directory", ), "CWLType", ) """ Extends primitive types with the concept of a file and directory as a builtin type. File: A File object Directory: A Directory object """ CWLArraySchemaLoader = _RecordLoader(CWLArraySchema, None, None) CWLRecordFieldLoader = _RecordLoader(CWLRecordField, None, None) CWLRecordSchemaLoader = _RecordLoader(CWLRecordSchema, None, None) FileLoader = _RecordLoader(File, None, None) DirectoryLoader = _RecordLoader(Directory, None, None) CWLObjectTypeLoader = _UnionLoader((), "CWLObjectTypeLoader") union_of_None_type_or_CWLObjectTypeLoader = _UnionLoader( ( None_type, CWLObjectTypeLoader, ) ) array_of_union_of_None_type_or_CWLObjectTypeLoader = _ArrayLoader( union_of_None_type_or_CWLObjectTypeLoader ) map_of_union_of_None_type_or_CWLObjectTypeLoader = _MapLoader( union_of_None_type_or_CWLObjectTypeLoader, "None", None, None ) InlineJavascriptRequirementLoader = _RecordLoader( InlineJavascriptRequirement, None, None ) SchemaDefRequirementLoader = _RecordLoader(SchemaDefRequirement, None, None) LoadListingRequirementLoader = _RecordLoader(LoadListingRequirement, None, None) DockerRequirementLoader = _RecordLoader(DockerRequirement, None, None) SoftwareRequirementLoader = _RecordLoader(SoftwareRequirement, None, None) InitialWorkDirRequirementLoader = _RecordLoader(InitialWorkDirRequirement, None, None) EnvVarRequirementLoader = _RecordLoader(EnvVarRequirement, None, None) ShellCommandRequirementLoader = _RecordLoader(ShellCommandRequirement, None, None) ResourceRequirementLoader = _RecordLoader(ResourceRequirement, None, None) WorkReuseLoader = _RecordLoader(WorkReuse, None, None) NetworkAccessLoader = _RecordLoader(NetworkAccess, None, None) InplaceUpdateRequirementLoader = _RecordLoader(InplaceUpdateRequirement, None, None) ToolTimeLimitLoader = _RecordLoader(ToolTimeLimit, None, None) SubworkflowFeatureRequirementLoader = _RecordLoader( SubworkflowFeatureRequirement, None, None ) ScatterFeatureRequirementLoader = _RecordLoader(ScatterFeatureRequirement, None, None) MultipleInputFeatureRequirementLoader = _RecordLoader( MultipleInputFeatureRequirement, None, None ) StepInputExpressionRequirementLoader = _RecordLoader( StepInputExpressionRequirement, None, None ) SecretsLoader = _RecordLoader(Secrets, None, None) MPIRequirementLoader = _RecordLoader(MPIRequirement, None, None) CUDARequirementLoader = _RecordLoader(CUDARequirement, None, None) ShmSizeLoader = _RecordLoader(ShmSize, None, None) union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_LoadListingRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_WorkReuseLoader_or_NetworkAccessLoader_or_InplaceUpdateRequirementLoader_or_ToolTimeLimitLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader_or_SecretsLoader_or_MPIRequirementLoader_or_CUDARequirementLoader_or_ShmSizeLoader = _UnionLoader( ( InlineJavascriptRequirementLoader, SchemaDefRequirementLoader, LoadListingRequirementLoader, DockerRequirementLoader, SoftwareRequirementLoader, InitialWorkDirRequirementLoader, EnvVarRequirementLoader, ShellCommandRequirementLoader, ResourceRequirementLoader, WorkReuseLoader, NetworkAccessLoader, InplaceUpdateRequirementLoader, ToolTimeLimitLoader, SubworkflowFeatureRequirementLoader, ScatterFeatureRequirementLoader, MultipleInputFeatureRequirementLoader, StepInputExpressionRequirementLoader, SecretsLoader, MPIRequirementLoader, CUDARequirementLoader, ShmSizeLoader, ) ) array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_LoadListingRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_WorkReuseLoader_or_NetworkAccessLoader_or_InplaceUpdateRequirementLoader_or_ToolTimeLimitLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader_or_SecretsLoader_or_MPIRequirementLoader_or_CUDARequirementLoader_or_ShmSizeLoader = _ArrayLoader( union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_LoadListingRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_WorkReuseLoader_or_NetworkAccessLoader_or_InplaceUpdateRequirementLoader_or_ToolTimeLimitLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader_or_SecretsLoader_or_MPIRequirementLoader_or_CUDARequirementLoader_or_ShmSizeLoader ) union_of_None_type_or_array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_LoadListingRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_WorkReuseLoader_or_NetworkAccessLoader_or_InplaceUpdateRequirementLoader_or_ToolTimeLimitLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader_or_SecretsLoader_or_MPIRequirementLoader_or_CUDARequirementLoader_or_ShmSizeLoader_or_CWLObjectTypeLoader = _UnionLoader( ( None_type, array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_LoadListingRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_WorkReuseLoader_or_NetworkAccessLoader_or_InplaceUpdateRequirementLoader_or_ToolTimeLimitLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader_or_SecretsLoader_or_MPIRequirementLoader_or_CUDARequirementLoader_or_ShmSizeLoader, CWLObjectTypeLoader, ) ) map_of_union_of_None_type_or_array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_LoadListingRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_WorkReuseLoader_or_NetworkAccessLoader_or_InplaceUpdateRequirementLoader_or_ToolTimeLimitLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader_or_SecretsLoader_or_MPIRequirementLoader_or_CUDARequirementLoader_or_ShmSizeLoader_or_CWLObjectTypeLoader = _MapLoader( union_of_None_type_or_array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_LoadListingRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_WorkReuseLoader_or_NetworkAccessLoader_or_InplaceUpdateRequirementLoader_or_ToolTimeLimitLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader_or_SecretsLoader_or_MPIRequirementLoader_or_CUDARequirementLoader_or_ShmSizeLoader_or_CWLObjectTypeLoader, "CWLInputFile", "@list", True, ) CWLInputFileLoader = map_of_union_of_None_type_or_array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_LoadListingRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_WorkReuseLoader_or_NetworkAccessLoader_or_InplaceUpdateRequirementLoader_or_ToolTimeLimitLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader_or_SecretsLoader_or_MPIRequirementLoader_or_CUDARequirementLoader_or_ShmSizeLoader_or_CWLObjectTypeLoader CWLVersionLoader = _EnumLoader( ( "draft-2", "draft-3.dev1", "draft-3.dev2", "draft-3.dev3", "draft-3.dev4", "draft-3.dev5", "draft-3", "draft-4.dev1", "draft-4.dev2", "draft-4.dev3", "v1.0.dev4", "v1.0", "v1.1.0-dev1", "v1.1", ), "CWLVersion", ) """ Version symbols for published CWL document versions. """ LoadListingEnumLoader = _EnumLoader( ( "no_listing", "shallow_listing", "deep_listing", ), "LoadListingEnum", ) """ Specify the desired behavior for loading the `listing` field of a Directory object for use by expressions. no_listing: Do not load the directory listing. shallow_listing: Only load the top level listing, do not recurse into subdirectories. deep_listing: Load the directory listing and recursively load all subdirectories as well. """ ExpressionLoader = _ExpressionLoader(str) InputBindingLoader = _RecordLoader(InputBinding, None, None) InputRecordFieldLoader = _RecordLoader(InputRecordField, None, None) InputRecordSchemaLoader = _RecordLoader(InputRecordSchema, None, None) InputEnumSchemaLoader = _RecordLoader(InputEnumSchema, None, None) InputArraySchemaLoader = _RecordLoader(InputArraySchema, None, None) OutputRecordFieldLoader = _RecordLoader(OutputRecordField, None, None) OutputRecordSchemaLoader = _RecordLoader(OutputRecordSchema, None, None) OutputEnumSchemaLoader = _RecordLoader(OutputEnumSchema, None, None) OutputArraySchemaLoader = _RecordLoader(OutputArraySchema, None, None) SecondaryFileSchemaLoader = _RecordLoader(SecondaryFileSchema, None, None) EnvironmentDefLoader = _RecordLoader(EnvironmentDef, None, None) CommandLineBindingLoader = _RecordLoader(CommandLineBinding, None, None) CommandOutputBindingLoader = _RecordLoader(CommandOutputBinding, None, None) CommandInputRecordFieldLoader = _RecordLoader(CommandInputRecordField, None, None) CommandInputRecordSchemaLoader = _RecordLoader(CommandInputRecordSchema, None, None) CommandInputEnumSchemaLoader = _RecordLoader(CommandInputEnumSchema, None, None) CommandInputArraySchemaLoader = _RecordLoader(CommandInputArraySchema, None, None) CommandOutputRecordFieldLoader = _RecordLoader(CommandOutputRecordField, None, None) CommandOutputRecordSchemaLoader = _RecordLoader(CommandOutputRecordSchema, None, None) CommandOutputEnumSchemaLoader = _RecordLoader(CommandOutputEnumSchema, None, None) CommandOutputArraySchemaLoader = _RecordLoader(CommandOutputArraySchema, None, None) CommandInputParameterLoader = _RecordLoader(CommandInputParameter, None, None) CommandOutputParameterLoader = _RecordLoader(CommandOutputParameter, None, None) stdinLoader = _EnumLoader(("stdin",), "stdin") """ Only valid as a `type` for a `CommandLineTool` input with no `inputBinding` set. `stdin` must not be specified at the `CommandLineTool` level. The following ``` inputs: an_input_name: type: stdin ``` is equivalent to ``` inputs: an_input_name: type: File streamable: true stdin: ${inputs.an_input_name.path} ``` """ stdoutLoader = _EnumLoader(("stdout",), "stdout") """ Only valid as a `type` for a `CommandLineTool` output with no `outputBinding` set. The following ``` outputs: an_output_name: type: stdout stdout: a_stdout_file ``` is equivalent to ``` outputs: an_output_name: type: File streamable: true outputBinding: glob: a_stdout_file stdout: a_stdout_file ``` If there is no `stdout` name provided, a random filename will be created. For example, the following ``` outputs: an_output_name: type: stdout ``` is equivalent to ``` outputs: an_output_name: type: File streamable: true outputBinding: glob: random_stdout_filenameABCDEFG stdout: random_stdout_filenameABCDEFG ``` """ stderrLoader = _EnumLoader(("stderr",), "stderr") """ Only valid as a `type` for a `CommandLineTool` output with no `outputBinding` set. The following ``` outputs: an_output_name: type: stderr stderr: a_stderr_file ``` is equivalent to ``` outputs: an_output_name: type: File streamable: true outputBinding: glob: a_stderr_file stderr: a_stderr_file ``` If there is no `stderr` name provided, a random filename will be created. For example, the following ``` outputs: an_output_name: type: stderr ``` is equivalent to ``` outputs: an_output_name: type: File streamable: true outputBinding: glob: random_stderr_filenameABCDEFG stderr: random_stderr_filenameABCDEFG ``` """ CommandLineToolLoader = _RecordLoader(CommandLineTool, None, None) SoftwarePackageLoader = _RecordLoader(SoftwarePackage, None, None) DirentLoader = _RecordLoader(Dirent, None, None) ExpressionToolOutputParameterLoader = _RecordLoader( ExpressionToolOutputParameter, None, None ) WorkflowInputParameterLoader = _RecordLoader(WorkflowInputParameter, None, None) ExpressionToolLoader = _RecordLoader(ExpressionTool, None, None) LinkMergeMethodLoader = _EnumLoader( ( "merge_nested", "merge_flattened", ), "LinkMergeMethod", ) """ The input link merge method, described in [WorkflowStepInput](#WorkflowStepInput). """ WorkflowOutputParameterLoader = _RecordLoader(WorkflowOutputParameter, None, None) WorkflowStepInputLoader = _RecordLoader(WorkflowStepInput, None, None) WorkflowStepOutputLoader = _RecordLoader(WorkflowStepOutput, None, None) ScatterMethodLoader = _EnumLoader( ( "dotproduct", "nested_crossproduct", "flat_crossproduct", ), "ScatterMethod", ) """ The scatter method, as described in [workflow step scatter](#WorkflowStep). """ WorkflowStepLoader = _RecordLoader(WorkflowStep, None, None) WorkflowLoader = _RecordLoader(Workflow, None, None) ProcessGeneratorLoader = _RecordLoader(ProcessGenerator, None, None) array_of_strtype = _ArrayLoader(strtype) union_of_None_type_or_strtype_or_array_of_strtype = _UnionLoader( ( None_type, strtype, array_of_strtype, ) ) uri_strtype_True_False_None_None = _URILoader(strtype, True, False, None, None) union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype = _UnionLoader( ( PrimitiveTypeLoader, RecordSchemaLoader, EnumSchemaLoader, ArraySchemaLoader, MapSchemaLoader, UnionSchemaLoader, strtype, ) ) array_of_union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype = _ArrayLoader( union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype ) union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype_or_array_of_union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype = _UnionLoader( ( PrimitiveTypeLoader, RecordSchemaLoader, EnumSchemaLoader, ArraySchemaLoader, MapSchemaLoader, UnionSchemaLoader, strtype, array_of_union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype, ) ) typedsl_union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype_or_array_of_union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype_2 = _TypeDSLLoader( union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype_or_array_of_union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype, 2, "v1.1", ) array_of_RecordFieldLoader = _ArrayLoader(RecordFieldLoader) union_of_None_type_or_array_of_RecordFieldLoader = _UnionLoader( ( None_type, array_of_RecordFieldLoader, ) ) idmap_fields_union_of_None_type_or_array_of_RecordFieldLoader = _IdMapLoader( union_of_None_type_or_array_of_RecordFieldLoader, "name", "type" ) Record_nameLoader = _EnumLoader(("record",), "Record_name") typedsl_Record_nameLoader_2 = _TypeDSLLoader(Record_nameLoader, 2, "v1.1") union_of_None_type_or_strtype = _UnionLoader( ( None_type, strtype, ) ) uri_union_of_None_type_or_strtype_True_False_None_None = _URILoader( union_of_None_type_or_strtype, True, False, None, None ) uri_array_of_strtype_True_False_None_None = _URILoader( array_of_strtype, True, False, None, None ) Enum_nameLoader = _EnumLoader(("enum",), "Enum_name") typedsl_Enum_nameLoader_2 = _TypeDSLLoader(Enum_nameLoader, 2, "v1.1") uri_union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype_or_array_of_union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype_False_True_2_None = _URILoader( union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype_or_array_of_union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype, False, True, 2, None, ) Array_nameLoader = _EnumLoader(("array",), "Array_name") typedsl_Array_nameLoader_2 = _TypeDSLLoader(Array_nameLoader, 2, "v1.1") Map_nameLoader = _EnumLoader(("map",), "Map_name") typedsl_Map_nameLoader_2 = _TypeDSLLoader(Map_nameLoader, 2, "v1.1") Union_nameLoader = _EnumLoader(("union",), "Union_name") typedsl_Union_nameLoader_2 = _TypeDSLLoader(Union_nameLoader, 2, "v1.1") union_of_PrimitiveTypeLoader_or_CWLRecordSchemaLoader_or_EnumSchemaLoader_or_CWLArraySchemaLoader_or_strtype = _UnionLoader( ( PrimitiveTypeLoader, CWLRecordSchemaLoader, EnumSchemaLoader, CWLArraySchemaLoader, strtype, ) ) array_of_union_of_PrimitiveTypeLoader_or_CWLRecordSchemaLoader_or_EnumSchemaLoader_or_CWLArraySchemaLoader_or_strtype = _ArrayLoader( union_of_PrimitiveTypeLoader_or_CWLRecordSchemaLoader_or_EnumSchemaLoader_or_CWLArraySchemaLoader_or_strtype ) union_of_PrimitiveTypeLoader_or_CWLRecordSchemaLoader_or_EnumSchemaLoader_or_CWLArraySchemaLoader_or_strtype_or_array_of_union_of_PrimitiveTypeLoader_or_CWLRecordSchemaLoader_or_EnumSchemaLoader_or_CWLArraySchemaLoader_or_strtype = _UnionLoader( ( PrimitiveTypeLoader, CWLRecordSchemaLoader, EnumSchemaLoader, CWLArraySchemaLoader, strtype, array_of_union_of_PrimitiveTypeLoader_or_CWLRecordSchemaLoader_or_EnumSchemaLoader_or_CWLArraySchemaLoader_or_strtype, ) ) uri_union_of_PrimitiveTypeLoader_or_CWLRecordSchemaLoader_or_EnumSchemaLoader_or_CWLArraySchemaLoader_or_strtype_or_array_of_union_of_PrimitiveTypeLoader_or_CWLRecordSchemaLoader_or_EnumSchemaLoader_or_CWLArraySchemaLoader_or_strtype_False_True_2_None = _URILoader( union_of_PrimitiveTypeLoader_or_CWLRecordSchemaLoader_or_EnumSchemaLoader_or_CWLArraySchemaLoader_or_strtype_or_array_of_union_of_PrimitiveTypeLoader_or_CWLRecordSchemaLoader_or_EnumSchemaLoader_or_CWLArraySchemaLoader_or_strtype, False, True, 2, None, ) typedsl_union_of_PrimitiveTypeLoader_or_CWLRecordSchemaLoader_or_EnumSchemaLoader_or_CWLArraySchemaLoader_or_strtype_or_array_of_union_of_PrimitiveTypeLoader_or_CWLRecordSchemaLoader_or_EnumSchemaLoader_or_CWLArraySchemaLoader_or_strtype_2 = _TypeDSLLoader( union_of_PrimitiveTypeLoader_or_CWLRecordSchemaLoader_or_EnumSchemaLoader_or_CWLArraySchemaLoader_or_strtype_or_array_of_union_of_PrimitiveTypeLoader_or_CWLRecordSchemaLoader_or_EnumSchemaLoader_or_CWLArraySchemaLoader_or_strtype, 2, "v1.1", ) array_of_CWLRecordFieldLoader = _ArrayLoader(CWLRecordFieldLoader) union_of_None_type_or_array_of_CWLRecordFieldLoader = _UnionLoader( ( None_type, array_of_CWLRecordFieldLoader, ) ) idmap_fields_union_of_None_type_or_array_of_CWLRecordFieldLoader = _IdMapLoader( union_of_None_type_or_array_of_CWLRecordFieldLoader, "name", "type" ) File_classLoader = _EnumLoader(("File",), "File_class") uri_File_classLoader_False_True_None_None = _URILoader( File_classLoader, False, True, None, None ) uri_union_of_None_type_or_strtype_False_False_None_None = _URILoader( union_of_None_type_or_strtype, False, False, None, None ) union_of_None_type_or_inttype = _UnionLoader( ( None_type, inttype, ) ) union_of_FileLoader_or_DirectoryLoader = _UnionLoader( ( FileLoader, DirectoryLoader, ) ) array_of_union_of_FileLoader_or_DirectoryLoader = _ArrayLoader( union_of_FileLoader_or_DirectoryLoader ) union_of_None_type_or_array_of_union_of_FileLoader_or_DirectoryLoader = _UnionLoader( ( None_type, array_of_union_of_FileLoader_or_DirectoryLoader, ) ) secondaryfilesdsl_union_of_None_type_or_array_of_union_of_FileLoader_or_DirectoryLoader = _UnionLoader( ( _SecondaryDSLLoader( union_of_None_type_or_array_of_union_of_FileLoader_or_DirectoryLoader ), union_of_None_type_or_array_of_union_of_FileLoader_or_DirectoryLoader, ) ) uri_union_of_None_type_or_strtype_True_False_None_True = _URILoader( union_of_None_type_or_strtype, True, False, None, True ) Directory_classLoader = _EnumLoader(("Directory",), "Directory_class") uri_Directory_classLoader_False_True_None_None = _URILoader( Directory_classLoader, False, True, None, None ) union_of_None_type_or_booltype = _UnionLoader( ( None_type, booltype, ) ) union_of_None_type_or_LoadListingEnumLoader = _UnionLoader( ( None_type, LoadListingEnumLoader, ) ) array_of_SecondaryFileSchemaLoader = _ArrayLoader(SecondaryFileSchemaLoader) union_of_None_type_or_SecondaryFileSchemaLoader_or_array_of_SecondaryFileSchemaLoader = _UnionLoader( ( None_type, SecondaryFileSchemaLoader, array_of_SecondaryFileSchemaLoader, ) ) secondaryfilesdsl_union_of_None_type_or_SecondaryFileSchemaLoader_or_array_of_SecondaryFileSchemaLoader = _UnionLoader( ( _SecondaryDSLLoader( union_of_None_type_or_SecondaryFileSchemaLoader_or_array_of_SecondaryFileSchemaLoader ), union_of_None_type_or_SecondaryFileSchemaLoader_or_array_of_SecondaryFileSchemaLoader, ) ) union_of_None_type_or_strtype_or_array_of_strtype_or_ExpressionLoader = _UnionLoader( ( None_type, strtype, array_of_strtype, ExpressionLoader, ) ) uri_union_of_None_type_or_strtype_or_array_of_strtype_or_ExpressionLoader_True_False_None_True = _URILoader( union_of_None_type_or_strtype_or_array_of_strtype_or_ExpressionLoader, True, False, None, True, ) union_of_None_type_or_strtype_or_ExpressionLoader = _UnionLoader( ( None_type, strtype, ExpressionLoader, ) ) uri_union_of_None_type_or_strtype_or_ExpressionLoader_True_False_None_True = _URILoader( union_of_None_type_or_strtype_or_ExpressionLoader, True, False, None, True ) union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype = _UnionLoader( ( CWLTypeLoader, InputRecordSchemaLoader, InputEnumSchemaLoader, InputArraySchemaLoader, strtype, ) ) array_of_union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype = _ArrayLoader( union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype ) union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype = _UnionLoader( ( CWLTypeLoader, InputRecordSchemaLoader, InputEnumSchemaLoader, InputArraySchemaLoader, strtype, array_of_union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype, ) ) typedsl_union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype_2 = _TypeDSLLoader( union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype, 2, "v1.1", ) array_of_InputRecordFieldLoader = _ArrayLoader(InputRecordFieldLoader) union_of_None_type_or_array_of_InputRecordFieldLoader = _UnionLoader( ( None_type, array_of_InputRecordFieldLoader, ) ) idmap_fields_union_of_None_type_or_array_of_InputRecordFieldLoader = _IdMapLoader( union_of_None_type_or_array_of_InputRecordFieldLoader, "name", "type" ) uri_union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype_False_True_2_None = _URILoader( union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype, False, True, 2, None, ) union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype = _UnionLoader( ( CWLTypeLoader, OutputRecordSchemaLoader, OutputEnumSchemaLoader, OutputArraySchemaLoader, strtype, ) ) array_of_union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype = _ArrayLoader( union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype ) union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype = _UnionLoader( ( CWLTypeLoader, OutputRecordSchemaLoader, OutputEnumSchemaLoader, OutputArraySchemaLoader, strtype, array_of_union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype, ) ) typedsl_union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype_2 = _TypeDSLLoader( union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype, 2, "v1.1", ) array_of_OutputRecordFieldLoader = _ArrayLoader(OutputRecordFieldLoader) union_of_None_type_or_array_of_OutputRecordFieldLoader = _UnionLoader( ( None_type, array_of_OutputRecordFieldLoader, ) ) idmap_fields_union_of_None_type_or_array_of_OutputRecordFieldLoader = _IdMapLoader( union_of_None_type_or_array_of_OutputRecordFieldLoader, "name", "type" ) uri_union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype_False_True_2_None = _URILoader( union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype, False, True, 2, None, ) union_of_CommandInputParameterLoader_or_WorkflowInputParameterLoader = _UnionLoader( ( CommandInputParameterLoader, WorkflowInputParameterLoader, ) ) array_of_union_of_CommandInputParameterLoader_or_WorkflowInputParameterLoader = ( _ArrayLoader(union_of_CommandInputParameterLoader_or_WorkflowInputParameterLoader) ) idmap_inputs_array_of_union_of_CommandInputParameterLoader_or_WorkflowInputParameterLoader = _IdMapLoader( array_of_union_of_CommandInputParameterLoader_or_WorkflowInputParameterLoader, "id", "type", ) union_of_CommandOutputParameterLoader_or_ExpressionToolOutputParameterLoader_or_WorkflowOutputParameterLoader = _UnionLoader( ( CommandOutputParameterLoader, ExpressionToolOutputParameterLoader, WorkflowOutputParameterLoader, ) ) array_of_union_of_CommandOutputParameterLoader_or_ExpressionToolOutputParameterLoader_or_WorkflowOutputParameterLoader = _ArrayLoader( union_of_CommandOutputParameterLoader_or_ExpressionToolOutputParameterLoader_or_WorkflowOutputParameterLoader ) idmap_outputs_array_of_union_of_CommandOutputParameterLoader_or_ExpressionToolOutputParameterLoader_or_WorkflowOutputParameterLoader = _IdMapLoader( array_of_union_of_CommandOutputParameterLoader_or_ExpressionToolOutputParameterLoader_or_WorkflowOutputParameterLoader, "id", "type", ) union_of_None_type_or_array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_LoadListingRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_WorkReuseLoader_or_NetworkAccessLoader_or_InplaceUpdateRequirementLoader_or_ToolTimeLimitLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader_or_SecretsLoader_or_MPIRequirementLoader_or_CUDARequirementLoader_or_ShmSizeLoader = _UnionLoader( ( None_type, array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_LoadListingRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_WorkReuseLoader_or_NetworkAccessLoader_or_InplaceUpdateRequirementLoader_or_ToolTimeLimitLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader_or_SecretsLoader_or_MPIRequirementLoader_or_CUDARequirementLoader_or_ShmSizeLoader, ) ) idmap_requirements_union_of_None_type_or_array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_LoadListingRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_WorkReuseLoader_or_NetworkAccessLoader_or_InplaceUpdateRequirementLoader_or_ToolTimeLimitLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader_or_SecretsLoader_or_MPIRequirementLoader_or_CUDARequirementLoader_or_ShmSizeLoader = _IdMapLoader( union_of_None_type_or_array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_LoadListingRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_WorkReuseLoader_or_NetworkAccessLoader_or_InplaceUpdateRequirementLoader_or_ToolTimeLimitLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader_or_SecretsLoader_or_MPIRequirementLoader_or_CUDARequirementLoader_or_ShmSizeLoader, "class", "None", ) union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_LoadListingRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_WorkReuseLoader_or_NetworkAccessLoader_or_InplaceUpdateRequirementLoader_or_ToolTimeLimitLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader_or_SecretsLoader_or_MPIRequirementLoader_or_CUDARequirementLoader_or_ShmSizeLoader_or_Any_type = _UnionLoader( ( InlineJavascriptRequirementLoader, SchemaDefRequirementLoader, LoadListingRequirementLoader, DockerRequirementLoader, SoftwareRequirementLoader, InitialWorkDirRequirementLoader, EnvVarRequirementLoader, ShellCommandRequirementLoader, ResourceRequirementLoader, WorkReuseLoader, NetworkAccessLoader, InplaceUpdateRequirementLoader, ToolTimeLimitLoader, SubworkflowFeatureRequirementLoader, ScatterFeatureRequirementLoader, MultipleInputFeatureRequirementLoader, StepInputExpressionRequirementLoader, SecretsLoader, MPIRequirementLoader, CUDARequirementLoader, ShmSizeLoader, Any_type, ) ) array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_LoadListingRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_WorkReuseLoader_or_NetworkAccessLoader_or_InplaceUpdateRequirementLoader_or_ToolTimeLimitLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader_or_SecretsLoader_or_MPIRequirementLoader_or_CUDARequirementLoader_or_ShmSizeLoader_or_Any_type = _ArrayLoader( union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_LoadListingRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_WorkReuseLoader_or_NetworkAccessLoader_or_InplaceUpdateRequirementLoader_or_ToolTimeLimitLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader_or_SecretsLoader_or_MPIRequirementLoader_or_CUDARequirementLoader_or_ShmSizeLoader_or_Any_type ) union_of_None_type_or_array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_LoadListingRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_WorkReuseLoader_or_NetworkAccessLoader_or_InplaceUpdateRequirementLoader_or_ToolTimeLimitLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader_or_SecretsLoader_or_MPIRequirementLoader_or_CUDARequirementLoader_or_ShmSizeLoader_or_Any_type = _UnionLoader( ( None_type, array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_LoadListingRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_WorkReuseLoader_or_NetworkAccessLoader_or_InplaceUpdateRequirementLoader_or_ToolTimeLimitLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader_or_SecretsLoader_or_MPIRequirementLoader_or_CUDARequirementLoader_or_ShmSizeLoader_or_Any_type, ) ) idmap_hints_union_of_None_type_or_array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_LoadListingRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_WorkReuseLoader_or_NetworkAccessLoader_or_InplaceUpdateRequirementLoader_or_ToolTimeLimitLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader_or_SecretsLoader_or_MPIRequirementLoader_or_CUDARequirementLoader_or_ShmSizeLoader_or_Any_type = _IdMapLoader( union_of_None_type_or_array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_LoadListingRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_WorkReuseLoader_or_NetworkAccessLoader_or_InplaceUpdateRequirementLoader_or_ToolTimeLimitLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader_or_SecretsLoader_or_MPIRequirementLoader_or_CUDARequirementLoader_or_ShmSizeLoader_or_Any_type, "class", "None", ) union_of_None_type_or_CWLVersionLoader = _UnionLoader( ( None_type, CWLVersionLoader, ) ) uri_union_of_None_type_or_CWLVersionLoader_False_True_None_None = _URILoader( union_of_None_type_or_CWLVersionLoader, False, True, None, None ) InlineJavascriptRequirement_classLoader = _EnumLoader( ("InlineJavascriptRequirement",), "InlineJavascriptRequirement_class" ) uri_InlineJavascriptRequirement_classLoader_False_True_None_None = _URILoader( InlineJavascriptRequirement_classLoader, False, True, None, None ) union_of_None_type_or_array_of_strtype = _UnionLoader( ( None_type, array_of_strtype, ) ) SchemaDefRequirement_classLoader = _EnumLoader( ("SchemaDefRequirement",), "SchemaDefRequirement_class" ) uri_SchemaDefRequirement_classLoader_False_True_None_None = _URILoader( SchemaDefRequirement_classLoader, False, True, None, None ) union_of_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader = _UnionLoader( ( CommandInputRecordSchemaLoader, CommandInputEnumSchemaLoader, CommandInputArraySchemaLoader, ) ) array_of_union_of_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader = _ArrayLoader( union_of_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader ) union_of_strtype_or_ExpressionLoader = _UnionLoader( ( strtype, ExpressionLoader, ) ) union_of_None_type_or_booltype_or_ExpressionLoader = _UnionLoader( ( None_type, booltype, ExpressionLoader, ) ) LoadListingRequirement_classLoader = _EnumLoader( ("LoadListingRequirement",), "LoadListingRequirement_class" ) uri_LoadListingRequirement_classLoader_False_True_None_None = _URILoader( LoadListingRequirement_classLoader, False, True, None, None ) union_of_None_type_or_inttype_or_ExpressionLoader = _UnionLoader( ( None_type, inttype, ExpressionLoader, ) ) union_of_None_type_or_strtype_or_ExpressionLoader_or_array_of_strtype = _UnionLoader( ( None_type, strtype, ExpressionLoader, array_of_strtype, ) ) union_of_None_type_or_ExpressionLoader = _UnionLoader( ( None_type, ExpressionLoader, ) ) union_of_None_type_or_CommandLineBindingLoader = _UnionLoader( ( None_type, CommandLineBindingLoader, ) ) union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype = _UnionLoader( ( CWLTypeLoader, CommandInputRecordSchemaLoader, CommandInputEnumSchemaLoader, CommandInputArraySchemaLoader, strtype, ) ) array_of_union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype = _ArrayLoader( union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype ) union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype = _UnionLoader( ( CWLTypeLoader, CommandInputRecordSchemaLoader, CommandInputEnumSchemaLoader, CommandInputArraySchemaLoader, strtype, array_of_union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype, ) ) typedsl_union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype_2 = _TypeDSLLoader( union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype, 2, "v1.1", ) array_of_CommandInputRecordFieldLoader = _ArrayLoader(CommandInputRecordFieldLoader) union_of_None_type_or_array_of_CommandInputRecordFieldLoader = _UnionLoader( ( None_type, array_of_CommandInputRecordFieldLoader, ) ) idmap_fields_union_of_None_type_or_array_of_CommandInputRecordFieldLoader = ( _IdMapLoader( union_of_None_type_or_array_of_CommandInputRecordFieldLoader, "name", "type" ) ) uri_union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype_False_True_2_None = _URILoader( union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype, False, True, 2, None, ) union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype = _UnionLoader( ( CWLTypeLoader, CommandOutputRecordSchemaLoader, CommandOutputEnumSchemaLoader, CommandOutputArraySchemaLoader, strtype, ) ) array_of_union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype = _ArrayLoader( union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype ) union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype = _UnionLoader( ( CWLTypeLoader, CommandOutputRecordSchemaLoader, CommandOutputEnumSchemaLoader, CommandOutputArraySchemaLoader, strtype, array_of_union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype, ) ) typedsl_union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype_2 = _TypeDSLLoader( union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype, 2, "v1.1", ) union_of_None_type_or_CommandOutputBindingLoader = _UnionLoader( ( None_type, CommandOutputBindingLoader, ) ) array_of_CommandOutputRecordFieldLoader = _ArrayLoader(CommandOutputRecordFieldLoader) union_of_None_type_or_array_of_CommandOutputRecordFieldLoader = _UnionLoader( ( None_type, array_of_CommandOutputRecordFieldLoader, ) ) idmap_fields_union_of_None_type_or_array_of_CommandOutputRecordFieldLoader = ( _IdMapLoader( union_of_None_type_or_array_of_CommandOutputRecordFieldLoader, "name", "type" ) ) uri_union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype_False_True_2_None = _URILoader( union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype, False, True, 2, None, ) union_of_CWLTypeLoader_or_stdinLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype = _UnionLoader( ( CWLTypeLoader, stdinLoader, CommandInputRecordSchemaLoader, CommandInputEnumSchemaLoader, CommandInputArraySchemaLoader, strtype, array_of_union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype, ) ) typedsl_union_of_CWLTypeLoader_or_stdinLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype_2 = _TypeDSLLoader( union_of_CWLTypeLoader_or_stdinLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype, 2, "v1.1", ) union_of_CWLTypeLoader_or_stdoutLoader_or_stderrLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype = _UnionLoader( ( CWLTypeLoader, stdoutLoader, stderrLoader, CommandOutputRecordSchemaLoader, CommandOutputEnumSchemaLoader, CommandOutputArraySchemaLoader, strtype, array_of_union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype, ) ) typedsl_union_of_CWLTypeLoader_or_stdoutLoader_or_stderrLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype_2 = _TypeDSLLoader( union_of_CWLTypeLoader_or_stdoutLoader_or_stderrLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype, 2, "v1.1", ) CommandLineTool_classLoader = _EnumLoader(("CommandLineTool",), "CommandLineTool_class") uri_CommandLineTool_classLoader_False_True_None_None = _URILoader( CommandLineTool_classLoader, False, True, None, None ) array_of_CommandInputParameterLoader = _ArrayLoader(CommandInputParameterLoader) idmap_inputs_array_of_CommandInputParameterLoader = _IdMapLoader( array_of_CommandInputParameterLoader, "id", "type" ) array_of_CommandOutputParameterLoader = _ArrayLoader(CommandOutputParameterLoader) idmap_outputs_array_of_CommandOutputParameterLoader = _IdMapLoader( array_of_CommandOutputParameterLoader, "id", "type" ) union_of_strtype_or_ExpressionLoader_or_CommandLineBindingLoader = _UnionLoader( ( strtype, ExpressionLoader, CommandLineBindingLoader, ) ) array_of_union_of_strtype_or_ExpressionLoader_or_CommandLineBindingLoader = ( _ArrayLoader(union_of_strtype_or_ExpressionLoader_or_CommandLineBindingLoader) ) union_of_None_type_or_array_of_union_of_strtype_or_ExpressionLoader_or_CommandLineBindingLoader = _UnionLoader( ( None_type, array_of_union_of_strtype_or_ExpressionLoader_or_CommandLineBindingLoader, ) ) array_of_inttype = _ArrayLoader(inttype) union_of_None_type_or_array_of_inttype = _UnionLoader( ( None_type, array_of_inttype, ) ) DockerRequirement_classLoader = _EnumLoader( ("DockerRequirement",), "DockerRequirement_class" ) uri_DockerRequirement_classLoader_False_True_None_None = _URILoader( DockerRequirement_classLoader, False, True, None, None ) SoftwareRequirement_classLoader = _EnumLoader( ("SoftwareRequirement",), "SoftwareRequirement_class" ) uri_SoftwareRequirement_classLoader_False_True_None_None = _URILoader( SoftwareRequirement_classLoader, False, True, None, None ) array_of_SoftwarePackageLoader = _ArrayLoader(SoftwarePackageLoader) idmap_packages_array_of_SoftwarePackageLoader = _IdMapLoader( array_of_SoftwarePackageLoader, "package", "specs" ) uri_union_of_None_type_or_array_of_strtype_False_False_None_True = _URILoader( union_of_None_type_or_array_of_strtype, False, False, None, True ) InitialWorkDirRequirement_classLoader = _EnumLoader( ("InitialWorkDirRequirement",), "InitialWorkDirRequirement_class" ) uri_InitialWorkDirRequirement_classLoader_False_True_None_None = _URILoader( InitialWorkDirRequirement_classLoader, False, True, None, None ) union_of_None_type_or_FileLoader_or_array_of_union_of_FileLoader_or_DirectoryLoader_or_DirectoryLoader_or_DirentLoader_or_ExpressionLoader = _UnionLoader( ( None_type, FileLoader, array_of_union_of_FileLoader_or_DirectoryLoader, DirectoryLoader, DirentLoader, ExpressionLoader, ) ) array_of_union_of_None_type_or_FileLoader_or_array_of_union_of_FileLoader_or_DirectoryLoader_or_DirectoryLoader_or_DirentLoader_or_ExpressionLoader = _ArrayLoader( union_of_None_type_or_FileLoader_or_array_of_union_of_FileLoader_or_DirectoryLoader_or_DirectoryLoader_or_DirentLoader_or_ExpressionLoader ) union_of_array_of_union_of_None_type_or_FileLoader_or_array_of_union_of_FileLoader_or_DirectoryLoader_or_DirectoryLoader_or_DirentLoader_or_ExpressionLoader_or_ExpressionLoader = _UnionLoader( ( array_of_union_of_None_type_or_FileLoader_or_array_of_union_of_FileLoader_or_DirectoryLoader_or_DirectoryLoader_or_DirentLoader_or_ExpressionLoader, ExpressionLoader, ) ) EnvVarRequirement_classLoader = _EnumLoader( ("EnvVarRequirement",), "EnvVarRequirement_class" ) uri_EnvVarRequirement_classLoader_False_True_None_None = _URILoader( EnvVarRequirement_classLoader, False, True, None, None ) array_of_EnvironmentDefLoader = _ArrayLoader(EnvironmentDefLoader) idmap_envDef_array_of_EnvironmentDefLoader = _IdMapLoader( array_of_EnvironmentDefLoader, "envName", "envValue" ) ShellCommandRequirement_classLoader = _EnumLoader( ("ShellCommandRequirement",), "ShellCommandRequirement_class" ) uri_ShellCommandRequirement_classLoader_False_True_None_None = _URILoader( ShellCommandRequirement_classLoader, False, True, None, None ) ResourceRequirement_classLoader = _EnumLoader( ("ResourceRequirement",), "ResourceRequirement_class" ) uri_ResourceRequirement_classLoader_False_True_None_None = _URILoader( ResourceRequirement_classLoader, False, True, None, None ) WorkReuse_classLoader = _EnumLoader(("WorkReuse",), "WorkReuse_class") uri_WorkReuse_classLoader_False_True_None_None = _URILoader( WorkReuse_classLoader, False, True, None, None ) union_of_booltype_or_ExpressionLoader = _UnionLoader( ( booltype, ExpressionLoader, ) ) NetworkAccess_classLoader = _EnumLoader(("NetworkAccess",), "NetworkAccess_class") uri_NetworkAccess_classLoader_False_True_None_None = _URILoader( NetworkAccess_classLoader, False, True, None, None ) InplaceUpdateRequirement_classLoader = _EnumLoader( ("InplaceUpdateRequirement",), "InplaceUpdateRequirement_class" ) uri_InplaceUpdateRequirement_classLoader_False_True_None_None = _URILoader( InplaceUpdateRequirement_classLoader, False, True, None, None ) ToolTimeLimit_classLoader = _EnumLoader(("ToolTimeLimit",), "ToolTimeLimit_class") uri_ToolTimeLimit_classLoader_False_True_None_None = _URILoader( ToolTimeLimit_classLoader, False, True, None, None ) union_of_inttype_or_ExpressionLoader = _UnionLoader( ( inttype, ExpressionLoader, ) ) union_of_None_type_or_InputBindingLoader = _UnionLoader( ( None_type, InputBindingLoader, ) ) ExpressionTool_classLoader = _EnumLoader(("ExpressionTool",), "ExpressionTool_class") uri_ExpressionTool_classLoader_False_True_None_None = _URILoader( ExpressionTool_classLoader, False, True, None, None ) array_of_WorkflowInputParameterLoader = _ArrayLoader(WorkflowInputParameterLoader) idmap_inputs_array_of_WorkflowInputParameterLoader = _IdMapLoader( array_of_WorkflowInputParameterLoader, "id", "type" ) array_of_ExpressionToolOutputParameterLoader = _ArrayLoader( ExpressionToolOutputParameterLoader ) idmap_outputs_array_of_ExpressionToolOutputParameterLoader = _IdMapLoader( array_of_ExpressionToolOutputParameterLoader, "id", "type" ) uri_union_of_None_type_or_strtype_or_array_of_strtype_False_False_1_None = _URILoader( union_of_None_type_or_strtype_or_array_of_strtype, False, False, 1, None ) union_of_None_type_or_LinkMergeMethodLoader = _UnionLoader( ( None_type, LinkMergeMethodLoader, ) ) uri_union_of_None_type_or_strtype_or_array_of_strtype_False_False_2_None = _URILoader( union_of_None_type_or_strtype_or_array_of_strtype, False, False, 2, None ) array_of_WorkflowStepInputLoader = _ArrayLoader(WorkflowStepInputLoader) idmap_in__array_of_WorkflowStepInputLoader = _IdMapLoader( array_of_WorkflowStepInputLoader, "id", "source" ) union_of_strtype_or_WorkflowStepOutputLoader = _UnionLoader( ( strtype, WorkflowStepOutputLoader, ) ) array_of_union_of_strtype_or_WorkflowStepOutputLoader = _ArrayLoader( union_of_strtype_or_WorkflowStepOutputLoader ) union_of_array_of_union_of_strtype_or_WorkflowStepOutputLoader = _UnionLoader( (array_of_union_of_strtype_or_WorkflowStepOutputLoader,) ) uri_union_of_array_of_union_of_strtype_or_WorkflowStepOutputLoader_True_False_None_None = _URILoader( union_of_array_of_union_of_strtype_or_WorkflowStepOutputLoader, True, False, None, None, ) array_of_Any_type = _ArrayLoader(Any_type) union_of_None_type_or_array_of_Any_type = _UnionLoader( ( None_type, array_of_Any_type, ) ) idmap_hints_union_of_None_type_or_array_of_Any_type = _IdMapLoader( union_of_None_type_or_array_of_Any_type, "class", "None" ) union_of_strtype_or_CommandLineToolLoader_or_ExpressionToolLoader_or_WorkflowLoader_or_ProcessGeneratorLoader = _UnionLoader( ( strtype, CommandLineToolLoader, ExpressionToolLoader, WorkflowLoader, ProcessGeneratorLoader, ) ) uri_union_of_strtype_or_CommandLineToolLoader_or_ExpressionToolLoader_or_WorkflowLoader_or_ProcessGeneratorLoader_False_False_None_None = _URILoader( union_of_strtype_or_CommandLineToolLoader_or_ExpressionToolLoader_or_WorkflowLoader_or_ProcessGeneratorLoader, False, False, None, None, ) uri_union_of_None_type_or_strtype_or_array_of_strtype_False_False_0_None = _URILoader( union_of_None_type_or_strtype_or_array_of_strtype, False, False, 0, None ) union_of_None_type_or_ScatterMethodLoader = _UnionLoader( ( None_type, ScatterMethodLoader, ) ) uri_union_of_None_type_or_ScatterMethodLoader_False_True_None_None = _URILoader( union_of_None_type_or_ScatterMethodLoader, False, True, None, None ) Workflow_classLoader = _EnumLoader(("Workflow",), "Workflow_class") uri_Workflow_classLoader_False_True_None_None = _URILoader( Workflow_classLoader, False, True, None, None ) array_of_WorkflowOutputParameterLoader = _ArrayLoader(WorkflowOutputParameterLoader) idmap_outputs_array_of_WorkflowOutputParameterLoader = _IdMapLoader( array_of_WorkflowOutputParameterLoader, "id", "type" ) array_of_WorkflowStepLoader = _ArrayLoader(WorkflowStepLoader) union_of_array_of_WorkflowStepLoader = _UnionLoader((array_of_WorkflowStepLoader,)) idmap_steps_union_of_array_of_WorkflowStepLoader = _IdMapLoader( union_of_array_of_WorkflowStepLoader, "id", "None" ) SubworkflowFeatureRequirement_classLoader = _EnumLoader( ("SubworkflowFeatureRequirement",), "SubworkflowFeatureRequirement_class" ) uri_SubworkflowFeatureRequirement_classLoader_False_True_None_None = _URILoader( SubworkflowFeatureRequirement_classLoader, False, True, None, None ) ScatterFeatureRequirement_classLoader = _EnumLoader( ("ScatterFeatureRequirement",), "ScatterFeatureRequirement_class" ) uri_ScatterFeatureRequirement_classLoader_False_True_None_None = _URILoader( ScatterFeatureRequirement_classLoader, False, True, None, None ) MultipleInputFeatureRequirement_classLoader = _EnumLoader( ("MultipleInputFeatureRequirement",), "MultipleInputFeatureRequirement_class" ) uri_MultipleInputFeatureRequirement_classLoader_False_True_None_None = _URILoader( MultipleInputFeatureRequirement_classLoader, False, True, None, None ) StepInputExpressionRequirement_classLoader = _EnumLoader( ("StepInputExpressionRequirement",), "StepInputExpressionRequirement_class" ) uri_StepInputExpressionRequirement_classLoader_False_True_None_None = _URILoader( StepInputExpressionRequirement_classLoader, False, True, None, None ) uri_strtype_False_True_None_None = _URILoader(strtype, False, True, None, None) uri_array_of_strtype_False_False_0_None = _URILoader( array_of_strtype, False, False, 0, None ) union_of_strtype_or_array_of_strtype = _UnionLoader( ( strtype, array_of_strtype, ) ) union_of_CommandLineToolLoader_or_ExpressionToolLoader_or_WorkflowLoader_or_ProcessGeneratorLoader = _UnionLoader( ( CommandLineToolLoader, ExpressionToolLoader, WorkflowLoader, ProcessGeneratorLoader, ) ) array_of_union_of_CommandLineToolLoader_or_ExpressionToolLoader_or_WorkflowLoader_or_ProcessGeneratorLoader = _ArrayLoader( union_of_CommandLineToolLoader_or_ExpressionToolLoader_or_WorkflowLoader_or_ProcessGeneratorLoader ) union_of_CommandLineToolLoader_or_ExpressionToolLoader_or_WorkflowLoader_or_ProcessGeneratorLoader_or_array_of_union_of_CommandLineToolLoader_or_ExpressionToolLoader_or_WorkflowLoader_or_ProcessGeneratorLoader = _UnionLoader( ( CommandLineToolLoader, ExpressionToolLoader, WorkflowLoader, ProcessGeneratorLoader, array_of_union_of_CommandLineToolLoader_or_ExpressionToolLoader_or_WorkflowLoader_or_ProcessGeneratorLoader, ) ) CWLObjectTypeLoader.add_loaders( ( booltype, inttype, floattype, strtype, FileLoader, DirectoryLoader, array_of_union_of_None_type_or_CWLObjectTypeLoader, map_of_union_of_None_type_or_CWLObjectTypeLoader, ) ) def load_document( doc: Any, baseuri: Optional[str] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> Any: if baseuri is None: baseuri = file_uri(os.getcwd()) + "/" if loadingOptions is None: loadingOptions = LoadingOptions() result, metadata = _document_load( union_of_CommandLineToolLoader_or_ExpressionToolLoader_or_WorkflowLoader_or_ProcessGeneratorLoader_or_array_of_union_of_CommandLineToolLoader_or_ExpressionToolLoader_or_WorkflowLoader_or_ProcessGeneratorLoader, doc, baseuri, loadingOptions, ) return result def load_document_with_metadata( doc: Any, baseuri: Optional[str] = None, loadingOptions: Optional[LoadingOptions] = None, addl_metadata_fields: Optional[MutableSequence[str]] = None, ) -> Any: if baseuri is None: baseuri = file_uri(os.getcwd()) + "/" if loadingOptions is None: loadingOptions = LoadingOptions(fileuri=baseuri) return _document_load( union_of_CommandLineToolLoader_or_ExpressionToolLoader_or_WorkflowLoader_or_ProcessGeneratorLoader_or_array_of_union_of_CommandLineToolLoader_or_ExpressionToolLoader_or_WorkflowLoader_or_ProcessGeneratorLoader, doc, baseuri, loadingOptions, addl_metadata_fields=addl_metadata_fields, ) def load_document_by_string( string: Any, uri: str, loadingOptions: Optional[LoadingOptions] = None, ) -> Any: yaml = yaml_no_ts() result = yaml.load(string) add_lc_filename(result, uri) if loadingOptions is None: loadingOptions = LoadingOptions(fileuri=uri) result, metadata = _document_load( union_of_CommandLineToolLoader_or_ExpressionToolLoader_or_WorkflowLoader_or_ProcessGeneratorLoader_or_array_of_union_of_CommandLineToolLoader_or_ExpressionToolLoader_or_WorkflowLoader_or_ProcessGeneratorLoader, result, uri, loadingOptions, ) return result def load_document_by_yaml( yaml: Any, uri: str, loadingOptions: Optional[LoadingOptions] = None, ) -> Any: """ Shortcut to load via a YAML object. yaml: must be from ruamel.yaml.main.YAML.load with preserve_quotes=True """ add_lc_filename(yaml, uri) if loadingOptions is None: loadingOptions = LoadingOptions(fileuri=uri) result, metadata = _document_load( union_of_CommandLineToolLoader_or_ExpressionToolLoader_or_WorkflowLoader_or_ProcessGeneratorLoader_or_array_of_union_of_CommandLineToolLoader_or_ExpressionToolLoader_or_WorkflowLoader_or_ProcessGeneratorLoader, yaml, uri, loadingOptions, ) return result cwl_utils-0.41/cwl_utils/parser/cwl_v1_1_utils.py0000644000000000000000000005277513615410400017111 0ustar00# SPDX-License-Identifier: Apache-2.0 import hashlib import logging from collections import namedtuple from collections.abc import MutableMapping, MutableSequence from io import StringIO from pathlib import Path from typing import IO, Any, cast from urllib.parse import urldefrag from schema_salad.exceptions import ValidationException from schema_salad.sourceline import SourceLine, add_lc_filename from schema_salad.utils import aslist, json_dumps, yaml_no_ts import cwl_utils.parser import cwl_utils.parser.cwl_v1_1 as cwl import cwl_utils.parser.utils from cwl_utils.errors import WorkflowException from cwl_utils.utils import yaml_dumps CONTENT_LIMIT: int = 64 * 1024 _logger = logging.getLogger("cwl_utils") SrcSink = namedtuple("SrcSink", ["src", "sink", "linkMerge", "message"]) def _compare_records( src: cwl.RecordSchema, sink: cwl.RecordSchema, strict: bool = False ) -> bool: """ Compare two records, ensuring they have compatible fields. This handles normalizing record names, which will be relative to workflow step, so that they can be compared. """ srcfields = {cwl.shortname(field.name): field.type_ for field in (src.fields or {})} sinkfields = { cwl.shortname(field.name): field.type_ for field in (sink.fields or {}) } for key in sinkfields.keys(): if ( not can_assign_src_to_sink( srcfields.get(key, "null"), sinkfields.get(key, "null"), strict ) and sinkfields.get(key) is not None ): _logger.info( "Record comparison failure for %s and %s\n" "Did not match fields for %s: %s and %s", cast(cwl.InputRecordSchema | cwl.CommandOutputRecordSchema, src).name, cast(cwl.InputRecordSchema | cwl.CommandOutputRecordSchema, sink).name, key, srcfields.get(key), sinkfields.get(key), ) return False return True def _compare_type(type1: Any, type2: Any) -> bool: match (type1, type1): case cwl.ArraySchema() as t1, cwl.ArraySchema() as t2: return _compare_type(t1.items, t2.items) case cwl.RecordSchema(), cwl.RecordSchema(): fields1 = { cwl.shortname(field.name): field.type_ for field in (type1.fields or {}) } fields2 = { cwl.shortname(field.name): field.type_ for field in (type2.fields or {}) } if fields1.keys() != fields2.keys(): return False return all(_compare_type(fields1[k], fields2[k]) for k in fields1.keys()) case MutableSequence(), MutableSequence(): if len(type1) != len(type2): return False for t3 in type1: if not any(_compare_type(t3, t2) for t2 in type2): return False return True return bool(type1 == type2) def _inputfile_load( doc: str | MutableMapping[str, Any] | MutableSequence[Any], baseuri: str, loadingOptions: cwl.LoadingOptions, addl_metadata_fields: MutableSequence[str] | None = None, ) -> tuple[Any, cwl.LoadingOptions]: loader = cwl.CWLInputFileLoader match doc: case str(): url = loadingOptions.fetcher.urljoin(baseuri, doc) if url in loadingOptions.idx: return loadingOptions.idx[url] doc_url, frg = urldefrag(url) text = loadingOptions.fetcher.fetch_text(doc_url) textIO = StringIO(text) textIO.name = doc_url yaml = yaml_no_ts() result = yaml.load(textIO) add_lc_filename(result, doc_url) loadingOptions = cwl.LoadingOptions( copyfrom=loadingOptions, fileuri=doc_url ) _inputfile_load( result, doc_url, loadingOptions, ) return loadingOptions.idx[url] case MutableMapping(): addl_metadata = {} if addl_metadata_fields is not None: for mf in addl_metadata_fields: if mf in doc: addl_metadata[mf] = doc[mf] loadingOptions = cwl.LoadingOptions( copyfrom=loadingOptions, baseuri=baseuri, addl_metadata=addl_metadata, ) loadingOptions.idx[baseuri] = ( loader.load(doc, baseuri, loadingOptions, docRoot=baseuri), loadingOptions, ) return loadingOptions.idx[baseuri] case MutableSequence(): loadingOptions.idx[baseuri] = ( loader.load(doc, baseuri, loadingOptions), loadingOptions, ) return loadingOptions.idx[baseuri] case _: raise ValidationException( "Expected URI string, MutableMapping or MutableSequence, got %s" % type(doc) ) def can_assign_src_to_sink(src: Any, sink: Any, strict: bool = False) -> bool: """ Check for identical type specifications, ignoring extra keys like inputBinding. src: admissible source types sink: admissible sink types In non-strict comparison, at least one source type must match one sink type, except for 'null'. In strict comparison, all source types must match at least one sink type. """ if "Any" in (src, sink): return True if isinstance(src, cwl.ArraySchema) and isinstance(sink, cwl.ArraySchema): return can_assign_src_to_sink(src.items, sink.items, strict) if isinstance(src, cwl.RecordSchema) and isinstance(sink, cwl.RecordSchema): return _compare_records(src, sink, strict) if isinstance(src, MutableSequence): if strict: for this_src in src: if not can_assign_src_to_sink(this_src, sink): return False return True for this_src in src: if this_src != "null" and can_assign_src_to_sink(this_src, sink): return True return False if isinstance(sink, MutableSequence): for this_sink in sink: if can_assign_src_to_sink(src, this_sink): return True return False return bool(src == sink) def check_all_types( src_dict: dict[str, Any], sinks: MutableSequence[cwl.WorkflowStepInput | cwl.WorkflowOutputParameter], type_dict: dict[str, Any], ) -> dict[str, list[SrcSink]]: """Given a list of sinks, check if their types match with the types of their sources.""" validation: dict[str, list[SrcSink]] = {"warning": [], "exception": []} for sink in sinks: match sink: case cwl.WorkflowOutputParameter(): sourceName = "outputSource" sourceField = sink.outputSource case cwl.WorkflowStepInput(): sourceName = "source" sourceField = sink.source case _: continue if sourceField is not None: if isinstance(sourceField, MutableSequence): linkMerge = sink.linkMerge or ( "merge_nested" if len(sourceField) > 1 else None ) srcs_of_sink = [] for parm_id in sourceField: srcs_of_sink += [src_dict[parm_id]] else: parm_id = cast(str, sourceField) if parm_id not in src_dict: raise SourceLine(sink, sourceName, ValidationException).makeError( f"{sourceName} not found: {parm_id}" ) srcs_of_sink = [src_dict[parm_id]] linkMerge = None for src in srcs_of_sink: check_result = check_types( type_dict[cast(str, src.id)], type_dict[sink.id], linkMerge, getattr(sink, "valueFrom", None), ) if check_result in ("warning", "exception"): validation[check_result].append(SrcSink(src, sink, linkMerge, None)) return validation def check_types( srctype: Any, sinktype: Any, linkMerge: str | None, valueFrom: str | None = None, ) -> str: """ Check if the source and sink types are correct. Acceptable types are "pass", "warning", or "exception". """ if valueFrom is not None: return "pass" if linkMerge is None: if can_assign_src_to_sink(srctype, sinktype, strict=True): return "pass" if can_assign_src_to_sink(srctype, sinktype, strict=False): return "warning" return "exception" if linkMerge == "merge_nested": return check_types( cwl.ArraySchema(items=srctype, type_="array"), sinktype, None, None ) if linkMerge == "merge_flattened": return check_types(merge_flatten_type(srctype), sinktype, None, None) raise ValidationException(f"Invalid value {linkMerge} for linkMerge field.") def content_limit_respected_read_bytes(f: IO[bytes]) -> bytes: """ Read file content up to 64 kB as a byte array. Truncate content for larger files. """ return f.read(CONTENT_LIMIT) def content_limit_respected_read(f: IO[bytes]) -> str: """ Read file content up to 64 kB as an utf-8 encoded string. Truncate content for larger files. """ return content_limit_respected_read_bytes(f).decode("utf-8") def convert_stdstreams_to_files(clt: cwl.CommandLineTool) -> None: """Convert stdin, stdout and stderr type shortcuts to files.""" for out in clt.outputs: if out.type_ == "stdout": if out.outputBinding is not None: raise ValidationException( "Not allowed to specify outputBinding when using stdout shortcut." ) if clt.stdout is None: clt.stdout = hashlib.sha1( # nosec json_dumps(clt.save(), sort_keys=True).encode("utf-8") ).hexdigest() out.type_ = "File" out.outputBinding = cwl.CommandOutputBinding(glob=clt.stdout) elif out.type_ == "stderr": if out.outputBinding is not None: raise ValidationException( "Not allowed to specify outputBinding when using stderr shortcut." ) if clt.stderr is None: clt.stderr = hashlib.sha1( # nosec json_dumps(clt.save(), sort_keys=True).encode("utf-8") ).hexdigest() out.type_ = "File" out.outputBinding = cwl.CommandOutputBinding(glob=clt.stderr) for inp in clt.inputs: if inp.type_ == "stdin": if inp.inputBinding is not None: raise ValidationException( "Not allowed to specify unputBinding when using stdin shortcut." ) if clt.stdin is not None: raise ValidationException( "Not allowed to specify stdin path when using stdin type shortcut." ) else: clt.stdin = ( "$(inputs.%s.path)" % cast(str, inp.id).rpartition("#")[2].split("/")[-1] ) inp.type_ = "File" def load_inputfile( doc: Any, baseuri: str | None = None, loadingOptions: cwl.LoadingOptions | None = None, ) -> Any: """Load a CWL v1.1 input file from a serialized YAML string or a YAML object.""" if baseuri is None: baseuri = cwl.file_uri(str(Path.cwd())) + "/" if loadingOptions is None: loadingOptions = cwl.LoadingOptions() result, metadata = _inputfile_load( doc, baseuri, loadingOptions, ) return result def load_inputfile_by_string( string: Any, uri: str, loadingOptions: cwl.LoadingOptions | None = None, ) -> Any: """Load a CWL v1.1 input file from a serialized YAML string.""" result = yaml_no_ts().load(string) add_lc_filename(result, uri) if loadingOptions is None: loadingOptions = cwl.LoadingOptions(fileuri=uri) result, metadata = _inputfile_load( result, uri, loadingOptions, ) return result def load_inputfile_by_yaml( yaml: Any, uri: str, loadingOptions: cwl.LoadingOptions | None = None, ) -> Any: """Load a CWL v1.1 input file from a YAML object.""" add_lc_filename(yaml, uri) if loadingOptions is None: loadingOptions = cwl.LoadingOptions(fileuri=uri) result, metadata = _inputfile_load( yaml, uri, loadingOptions, ) return result def merge_flatten_type(src: Any) -> Any: """Return the merge flattened type of the source type.""" if isinstance(src, MutableSequence): return [merge_flatten_type(t) for t in src] if isinstance(src, cwl.ArraySchema): return src return cwl.ArraySchema(type_="array", items=src) def type_for_step_input( step: cwl.WorkflowStep, in_: cwl.WorkflowStepInput, ) -> Any: """Determine the type for the given step input.""" if in_.valueFrom is not None: return "Any" step_run = cwl_utils.parser.utils.load_step(step) cwl_utils.parser.utils.convert_stdstreams_to_files(step_run) if step_run and step_run.inputs: for step_input in step_run.inputs: if cast(str, step_input.id).split("#")[-1] == in_.id.split("#")[-1]: input_type = step_input.type_ if step.scatter is not None and in_.id in aslist(step.scatter): input_type = cwl.ArraySchema(items=input_type, type_="array") return input_type return "Any" def type_for_step_output( step: cwl.WorkflowStep, sourcename: str, ) -> Any: """Determine the type for the given step output.""" step_run = cwl_utils.parser.utils.load_step(step) cwl_utils.parser.utils.convert_stdstreams_to_files(step_run) if step_run and step_run.outputs: for output in step_run.outputs: if ( output.id.split("#")[-1].split("/")[-1] == sourcename.split("#")[-1].split("/")[-1] ): output_type = output.type_ if step.scatter is not None: if step.scatterMethod == "nested_crossproduct": for _ in range(len(aslist(step.scatter))): output_type = cwl.ArraySchema( items=output_type, type_="array" ) else: output_type = cwl.ArraySchema(items=output_type, type_="array") return output_type raise ValidationException( "param {} not found in {}.".format( sourcename, yaml_dumps(cwl.save(step)), ) ) def type_for_source( process: cwl.CommandLineTool | cwl.Workflow | cwl.ExpressionTool, sourcenames: str | list[str], parent: cwl.Workflow | None = None, linkMerge: str | None = None, ) -> Any: """Determine the type for the given sourcenames.""" scatter_context: list[tuple[int, str] | None] = [] params = param_for_source_id(process, sourcenames, parent, scatter_context) if not isinstance(params, MutableSequence): new_type = params.type_ if scatter_context[0] is not None: if scatter_context[0][1] == "nested_crossproduct": for _ in range(scatter_context[0][0]): new_type = cwl.ArraySchema(items=new_type, type_="array") else: new_type = cwl.ArraySchema(items=new_type, type_="array") if linkMerge == "merge_nested": new_type = cwl.ArraySchema(items=new_type, type_="array") elif linkMerge == "merge_flattened": new_type = merge_flatten_type(new_type) return new_type new_type = [] for p, sc in zip(params, scatter_context): if isinstance(p, str) and not any(_compare_type(t, p) for t in new_type): cur_type = p elif hasattr(p, "type_") and not any( _compare_type(t, p.type_) for t in new_type ): cur_type = p.type_ else: cur_type = None if cur_type is not None: if sc is not None: if sc[1] == "nested_crossproduct": for _ in range(sc[0]): cur_type = cwl.ArraySchema(items=cur_type, type_="array") else: cur_type = cwl.ArraySchema(items=cur_type, type_="array") new_type.append(cur_type) if len(new_type) == 1: new_type = new_type[0] if linkMerge == "merge_nested": return cwl.ArraySchema(items=new_type, type_="array") elif linkMerge == "merge_flattened": return merge_flatten_type(new_type) elif isinstance(sourcenames, list) and len(sourcenames) > 1: return cwl.ArraySchema(items=new_type, type_="array") else: return new_type def param_for_source_id( process: cwl.CommandLineTool | cwl.Workflow | cwl.ExpressionTool, sourcenames: str | list[str], parent: cwl.Workflow | None = None, scatter_context: list[tuple[int, str] | None] | None = None, ) -> ( cwl.CommandInputParameter | cwl.CommandOutputParameter | cwl.WorkflowInputParameter | MutableSequence[ cwl.CommandInputParameter | cwl.CommandOutputParameter | cwl.WorkflowInputParameter ] ): """Find the process input parameter that matches one of the given sourcenames.""" if isinstance(sourcenames, str): sourcenames = [sourcenames] params: MutableSequence[ cwl.CommandInputParameter | cwl.CommandOutputParameter | cwl.WorkflowInputParameter ] = [] for sourcename in sourcenames: if not isinstance(process, cwl.Workflow): for param in process.inputs: if param.id.split("#")[-1] == sourcename.split("#")[-1]: params.append(param) if scatter_context is not None: scatter_context.append(None) targets = [process] if parent: targets.append(parent) for target in targets: if isinstance(target, cwl.Workflow): for inp in target.inputs: if inp.id.split("#")[-1] == sourcename.split("#")[-1]: params.append(inp) if scatter_context is not None: scatter_context.append(None) for step in target.steps: if ( "/".join(sourcename.split("#")[-1].split("/")[:-1]) == step.id.split("#")[-1] and step.out ): step_run = cwl_utils.parser.utils.load_step(step) cwl_utils.parser.utils.convert_stdstreams_to_files(step_run) for outp in step.out: outp_id = outp if isinstance(outp, str) else outp.id if ( outp_id.split("#")[-1].split("/")[-1] == sourcename.split("#")[-1].split("/")[-1] ): if step_run and step_run.outputs: for output in step_run.outputs: if ( output.id.split("#")[-1].split("/")[-1] == sourcename.split("#")[-1].split("/")[-1] ): params.append(output) if scatter_context is not None: if scatter_context is not None: if isinstance(step.scatter, str): scatter_context.append( ( 1, step.scatterMethod or "dotproduct", ) ) elif isinstance( step.scatter, MutableSequence ): scatter_context.append( ( len(step.scatter), step.scatterMethod or "dotproduct", ) ) else: scatter_context.append(None) if len(params) == 1: return params[0] elif len(params) > 1: return params raise WorkflowException( "param {} not found in {}\n{}.".format( sourcename, yaml_dumps(cwl.save(process)), (f" or\n {yaml_dumps(cwl.save(parent))}" if parent is not None else ""), ) ) cwl_utils-0.41/cwl_utils/parser/cwl_v1_2.py0000644000000000000000000500704613615410400015666 0ustar00# # This file was autogenerated using schema-salad-tool --codegen=python # The code itself is released under the Apache 2.0 license and the help text is # subject to the license of the original schema. import copy import logging import os import pathlib import tempfile import uuid as _uuid__ # pylint: disable=unused-import # noqa: F401 import xml.sax # nosec from abc import ABC, abstractmethod from collections.abc import MutableMapping, MutableSequence, Sequence from io import StringIO from itertools import chain from typing import Any, Final, Optional, Union, cast from urllib.parse import quote, urldefrag, urlparse, urlsplit, urlunsplit from urllib.request import pathname2url from rdflib import Graph from rdflib.plugins.parsers.notation3 import BadSyntax from ruamel.yaml.comments import CommentedMap from schema_salad.exceptions import SchemaSaladException, ValidationException from schema_salad.fetcher import DefaultFetcher, Fetcher, MemoryCachingFetcher from schema_salad.sourceline import SourceLine, add_lc_filename from schema_salad.utils import CacheType, yaml_no_ts # requires schema-salad v8.2+ _vocab: dict[str, str] = {} _rvocab: dict[str, str] = {} _logger: Final = logging.getLogger("salad") IdxType = MutableMapping[str, tuple[Any, "LoadingOptions"]] class LoadingOptions: idx: Final[IdxType] fileuri: Final[Optional[str]] baseuri: Final[str] namespaces: Final[MutableMapping[str, str]] schemas: Final[MutableSequence[str]] original_doc: Final[Optional[Any]] addl_metadata: Final[MutableMapping[str, Any]] fetcher: Final[Fetcher] vocab: Final[dict[str, str]] rvocab: Final[dict[str, str]] cache: Final[CacheType] imports: Final[list[str]] includes: Final[list[str]] no_link_check: Final[Optional[bool]] container: Final[Optional[str]] def __init__( self, fetcher: Optional[Fetcher] = None, namespaces: Optional[dict[str, str]] = None, schemas: Optional[list[str]] = None, fileuri: Optional[str] = None, copyfrom: Optional["LoadingOptions"] = None, original_doc: Optional[Any] = None, addl_metadata: Optional[dict[str, str]] = None, baseuri: Optional[str] = None, idx: Optional[IdxType] = None, imports: Optional[list[str]] = None, includes: Optional[list[str]] = None, no_link_check: Optional[bool] = None, container: Optional[str] = None, ) -> None: """Create a LoadingOptions object.""" self.original_doc = original_doc if idx is not None: temp_idx = idx else: temp_idx = copyfrom.idx if copyfrom is not None else {} self.idx = temp_idx if fileuri is not None: temp_fileuri: Optional[str] = fileuri else: temp_fileuri = copyfrom.fileuri if copyfrom is not None else None self.fileuri = temp_fileuri if baseuri is not None: temp_baseuri = baseuri else: temp_baseuri = copyfrom.baseuri if copyfrom is not None else "" self.baseuri = temp_baseuri if namespaces is not None: temp_namespaces: MutableMapping[str, str] = namespaces else: temp_namespaces = copyfrom.namespaces if copyfrom is not None else {} self.namespaces = temp_namespaces if schemas is not None: temp_schemas: MutableSequence[str] = schemas else: temp_schemas = copyfrom.schemas if copyfrom is not None else [] self.schemas = temp_schemas if addl_metadata is not None: temp_addl_metadata: MutableMapping[str, Any] = addl_metadata else: temp_addl_metadata = copyfrom.addl_metadata if copyfrom is not None else {} self.addl_metadata = temp_addl_metadata if imports is not None: temp_imports = imports else: temp_imports = copyfrom.imports if copyfrom is not None else [] self.imports = temp_imports if includes is not None: temp_includes = includes else: temp_includes = copyfrom.includes if copyfrom is not None else [] self.includes = temp_includes if no_link_check is not None: temp_no_link_check: Optional[bool] = no_link_check else: temp_no_link_check = copyfrom.no_link_check if copyfrom is not None else False self.no_link_check = temp_no_link_check if container is not None: temp_container: Optional[str] = container else: temp_container = copyfrom.container if copyfrom is not None else None self.container = temp_container if fetcher is not None: temp_fetcher = fetcher elif copyfrom is not None: temp_fetcher = copyfrom.fetcher else: import requests from cachecontrol.caches import SeparateBodyFileCache from cachecontrol.wrapper import CacheControl root = pathlib.Path(os.environ.get("HOME", tempfile.gettempdir())) session = CacheControl( requests.Session(), cache=SeparateBodyFileCache(root / ".cache" / "salad"), ) temp_fetcher = DefaultFetcher({}, session) self.fetcher = temp_fetcher self.cache = self.fetcher.cache if isinstance(self.fetcher, MemoryCachingFetcher) else {} if self.namespaces != {}: temp_vocab = _vocab.copy() temp_rvocab = _rvocab.copy() for k, v in self.namespaces.items(): temp_vocab[k] = v temp_rvocab[v] = k else: temp_vocab = _vocab temp_rvocab = _rvocab self.vocab = temp_vocab self.rvocab = temp_rvocab @property def graph(self) -> Graph: """Generate a merged rdflib.Graph from all entries in self.schemas.""" graph = Graph() if not self.schemas: return graph key: Final = str(hash(tuple(self.schemas))) if key in self.cache: return cast(Graph, self.cache[key]) for schema in self.schemas: fetchurl = ( self.fetcher.urljoin(self.fileuri, schema) if self.fileuri is not None else pathlib.Path(schema).resolve().as_uri() ) if fetchurl not in self.cache or self.cache[fetchurl] is True: _logger.debug("Getting external schema %s", fetchurl) try: content = self.fetcher.fetch_text(fetchurl) except Exception as e: _logger.warning("Could not load extension schema %s: %s", fetchurl, str(e)) continue newGraph = Graph() err_msg = "unknown error" for fmt in ["xml", "turtle"]: try: newGraph.parse(data=content, format=fmt, publicID=str(fetchurl)) self.cache[fetchurl] = newGraph graph += newGraph break except (xml.sax.SAXParseException, TypeError, BadSyntax) as e: err_msg = str(e) else: _logger.warning("Could not load extension schema %s: %s", fetchurl, err_msg) self.cache[key] = graph return graph class Saveable(ABC): """Mark classes than have a save() and fromDoc() function.""" @classmethod @abstractmethod def fromDoc( cls, _doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None, ) -> "Saveable": """Construct this object from the result of yaml.load().""" @abstractmethod def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: """Convert this object to a JSON/YAML friendly dictionary.""" def load_field( val: Union[str, dict[str, str]], fieldtype: "_Loader", baseuri: str, loadingOptions: LoadingOptions, lc: Optional[list[Any]] = None, ) -> Any: """Load field.""" if isinstance(val, MutableMapping): if "$import" in val: if loadingOptions.fileuri is None: raise SchemaSaladException("Cannot load $import without fileuri") url1: Final = loadingOptions.fetcher.urljoin(loadingOptions.fileuri, val["$import"]) result, metadata = _document_load_by_url( fieldtype, url1, loadingOptions, ) loadingOptions.imports.append(url1) return result if "$include" in val: if loadingOptions.fileuri is None: raise SchemaSaladException("Cannot load $import without fileuri") url2: Final = loadingOptions.fetcher.urljoin(loadingOptions.fileuri, val["$include"]) val = loadingOptions.fetcher.fetch_text(url2) loadingOptions.includes.append(url2) return fieldtype.load(val, baseuri, loadingOptions, lc=lc) save_type = Optional[Union[MutableMapping[str, Any], MutableSequence[Any], int, float, bool, str]] def extract_type(val_type: type[Any]) -> str: """Take a type of value, and extracts the value as a string.""" val_str: Final = str(val_type) return val_str.split("'")[1] def convert_typing(val_type: str) -> str: """Normalize type names to schema-salad types.""" if "None" in val_type: return "null" if "CommentedSeq" in val_type or "list" in val_type: return "array" if "CommentedMap" in val_type or "dict" in val_type: return "object" if "False" in val_type or "True" in val_type: return "boolean" return val_type def parse_errors(error_message: str) -> tuple[str, str, str]: """Parse error messages from several loaders into one error message.""" if not error_message.startswith("Expected"): return error_message, "", "" vals: Final = error_message.split("\n") if len(vals) == 1: return error_message, "", "" types1: Final = set() for val in vals: individual_vals = val.split(" ") if val == "": continue if individual_vals[1] == "one": individual_vals = val.split("(")[1].split(",") for t in individual_vals: types1.add(t.strip(" ").strip(")\n")) elif individual_vals[2] == "").replace("'", "")) elif individual_vals[0] == "Value": types1.add(individual_vals[-1].strip(".")) else: types1.add(individual_vals[1].replace(",", "")) types2: Final = {val for val in types1 if val != "NoneType"} if "str" in types2: types3 = {convert_typing(val) for val in types2 if "'" not in val} else: types3 = types2 to_print = "" for val in types3: if "'" in val: to_print = "value" if len(types3) == 1 else "values" if to_print == "": to_print = "type" if len(types3) == 1 else "types" verb_tensage: Final = "is" if len(types3) == 1 else "are" return str(types3).replace("{", "(").replace("}", ")").replace("'", ""), to_print, verb_tensage def save( val: Any, top: bool = True, base_url: str = "", relative_uris: bool = True, ) -> save_type: if isinstance(val, Saveable): return val.save(top=top, base_url=base_url, relative_uris=relative_uris) if isinstance(val, MutableSequence): return [save(v, top=False, base_url=base_url, relative_uris=relative_uris) for v in val] if isinstance(val, MutableMapping): newdict: Final = {} for key in val: newdict[key] = save(val[key], top=False, base_url=base_url, relative_uris=relative_uris) return newdict if val is None or isinstance(val, (int, float, bool, str)): return val raise Exception("Not Saveable: %s" % type(val)) def save_with_metadata( val: Any, valLoadingOpts: LoadingOptions, top: bool = True, base_url: str = "", relative_uris: bool = True, ) -> save_type: """Save and set $namespaces, $schemas, $base and any other metadata fields at the top level.""" saved_val: Final = save(val, top, base_url, relative_uris) newdict: MutableMapping[str, Any] = {} if isinstance(saved_val, MutableSequence): newdict = {"$graph": saved_val} elif isinstance(saved_val, MutableMapping): newdict = saved_val if valLoadingOpts.namespaces: newdict["$namespaces"] = valLoadingOpts.namespaces if valLoadingOpts.schemas: newdict["$schemas"] = valLoadingOpts.schemas if valLoadingOpts.baseuri: newdict["$base"] = valLoadingOpts.baseuri for k, v in valLoadingOpts.addl_metadata.items(): if k not in newdict: newdict[k] = v return newdict def expand_url( url: str, base_url: str, loadingOptions: LoadingOptions, scoped_id: bool = False, vocab_term: bool = False, scoped_ref: Optional[int] = None, ) -> str: if url in ("@id", "@type"): return url if vocab_term and url in loadingOptions.vocab: return url if bool(loadingOptions.vocab) and ":" in url: prefix: Final = url.split(":")[0] if prefix in loadingOptions.vocab: url = loadingOptions.vocab[prefix] + url[len(prefix) + 1 :] split1: Final = urlsplit(url) if ( (bool(split1.scheme) and split1.scheme in loadingOptions.fetcher.supported_schemes()) or url.startswith("$(") or url.startswith("${") ): pass elif scoped_id and not bool(split1.fragment): splitbase1: Final = urlsplit(base_url) frg: str if bool(splitbase1.fragment): frg = splitbase1.fragment + "/" + split1.path else: frg = split1.path pt: Final = splitbase1.path if splitbase1.path != "" else "/" url = urlunsplit((splitbase1.scheme, splitbase1.netloc, pt, splitbase1.query, frg)) elif scoped_ref is not None and not bool(split1.fragment): splitbase2: Final = urlsplit(base_url) sp = splitbase2.fragment.split("/") n = scoped_ref while n > 0 and len(sp) > 0: sp.pop() n -= 1 sp.append(url) url = urlunsplit( ( splitbase2.scheme, splitbase2.netloc, splitbase2.path, splitbase2.query, "/".join(sp), ) ) else: url = loadingOptions.fetcher.urljoin(base_url, url) if vocab_term: split2: Final = urlsplit(url) if bool(split2.scheme): if url in loadingOptions.rvocab: return loadingOptions.rvocab[url] else: raise ValidationException(f"Term {url!r} not in vocabulary") return url class _Loader: def load( self, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None, lc: Optional[list[Any]] = None, ) -> Any: pass class _AnyLoader(_Loader): def load( self, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None, lc: Optional[list[Any]] = None, ) -> Any: if doc is not None: return doc raise ValidationException("Expected non-null") class _PrimitiveLoader(_Loader): def __init__(self, tp: Union[type, tuple[type[str], type[str]]]) -> None: self.tp: Final = tp def load( self, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None, lc: Optional[list[Any]] = None, ) -> Any: if not isinstance(doc, self.tp): raise ValidationException(f"Expected a {self.tp} but got {doc.__class__.__name__}") return doc def __repr__(self) -> str: return str(self.tp) class _ArrayLoader(_Loader): def __init__(self, items: _Loader) -> None: self.items: Final = items def load( self, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None, lc: Optional[list[Any]] = None, ) -> Any: if not isinstance(doc, MutableSequence): raise ValidationException( f"Value is a {convert_typing(extract_type(type(doc)))}, " f"but valid type for this field is an array." ) r: Final[list[Any]] = [] errors: Final[list[SchemaSaladException]] = [] fields: Final[list[str]] = [] for i in range(0, len(doc)): try: lf = load_field( doc[i], _UnionLoader([self, self.items]), baseuri, loadingOptions, lc=lc ) flatten = loadingOptions.container != "@list" if flatten and isinstance(lf, MutableSequence): r.extend(lf) else: r.append(lf) if isinstance(doc[i], CommentedMap): if doc[i].get("id") is not None: if doc[i].get("id") in fields: errors.append( ValidationException( f"Duplicate field {doc[i].get('id')!r}", SourceLine(doc[i], "id", str), [], ) ) else: fields.append(doc[i].get("id")) except ValidationException as e: e = ValidationException( "array item is invalid because", SourceLine(doc, i, str), [e] ) errors.append(e) if errors: raise ValidationException("", None, errors) return r def __repr__(self) -> str: return f"array<{self.items}>" class _MapLoader(_Loader): def __init__( self, values: _Loader, name: Optional[str] = None, container: Optional[str] = None, no_link_check: Optional[bool] = None, ) -> None: self.values: Final = values self.name: Final = name self.container: Final = container self.no_link_check: Final = no_link_check def load( self, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None, lc: Optional[list[Any]] = None, ) -> Any: if not isinstance(doc, MutableMapping): raise ValidationException(f"Expected a map, was {type(doc)}") if self.container is not None or self.no_link_check is not None: loadingOptions = LoadingOptions( copyfrom=loadingOptions, container=self.container, no_link_check=self.no_link_check ) r: Final[dict[str, Any]] = {} errors: Final[list[SchemaSaladException]] = [] for k, v in doc.items(): try: lf = load_field(v, self.values, baseuri, loadingOptions, lc) r[k] = lf except ValidationException as e: errors.append(e.with_sourceline(SourceLine(doc, k, str))) if errors: raise ValidationException("", None, errors) return r def __repr__(self) -> str: return self.name if self.name is not None else f"map" class _EnumLoader(_Loader): def __init__(self, symbols: Sequence[str], name: str) -> None: self.symbols: Final = symbols self.name: Final = name def load( self, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None, lc: Optional[list[Any]] = None, ) -> Any: if doc in self.symbols: return doc raise ValidationException(f"Expected one of {self.symbols}") def __repr__(self) -> str: return self.name class _SecondaryDSLLoader(_Loader): def __init__(self, inner: _Loader) -> None: self.inner: Final = inner def load( self, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None, lc: Optional[list[Any]] = None, ) -> Any: r: Final[list[dict[str, Any]]] = [] if isinstance(doc, MutableSequence): for d in doc: if isinstance(d, str): if d.endswith("?"): r.append({"pattern": d[:-1], "required": False}) else: r.append({"pattern": d}) elif isinstance(d, dict): new_dict1: dict[str, Any] = {} dict_copy = copy.deepcopy(d) if "pattern" in dict_copy: new_dict1["pattern"] = dict_copy.pop("pattern") else: raise ValidationException( f"Missing pattern in secondaryFiles specification entry: {d}" ) new_dict1["required"] = ( dict_copy.pop("required") if "required" in dict_copy else None ) if len(dict_copy): raise ValidationException( "Unallowed values in secondaryFiles specification entry: {}".format( dict_copy ) ) r.append(new_dict1) else: raise ValidationException( "Expected a string or sequence of (strings or mappings)." ) elif isinstance(doc, MutableMapping): new_dict2: Final = {} doc_copy: Final = copy.deepcopy(doc) if "pattern" in doc_copy: new_dict2["pattern"] = doc_copy.pop("pattern") else: raise ValidationException( f"Missing pattern in secondaryFiles specification entry: {doc}" ) new_dict2["required"] = doc_copy.pop("required") if "required" in doc_copy else None if len(doc_copy): raise ValidationException( f"Unallowed values in secondaryFiles specification entry: {doc_copy}" ) r.append(new_dict2) elif isinstance(doc, str): if doc.endswith("?"): r.append({"pattern": doc[:-1], "required": False}) else: r.append({"pattern": doc}) else: raise ValidationException("Expected str or sequence of str") return self.inner.load(r, baseuri, loadingOptions, docRoot, lc=lc) class _RecordLoader(_Loader): def __init__( self, classtype: type[Saveable], container: Optional[str] = None, no_link_check: Optional[bool] = None, ) -> None: self.classtype: Final = classtype self.container: Final = container self.no_link_check: Final = no_link_check def load( self, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None, lc: Optional[list[Any]] = None, ) -> Any: if not isinstance(doc, MutableMapping): raise ValidationException( f"Value is a {convert_typing(extract_type(type(doc)))}, " f"but valid type for this field is an object." ) if self.container is not None or self.no_link_check is not None: loadingOptions = LoadingOptions( copyfrom=loadingOptions, container=self.container, no_link_check=self.no_link_check ) return self.classtype.fromDoc(doc, baseuri, loadingOptions, docRoot=docRoot) def __repr__(self) -> str: return str(self.classtype.__name__) class _ExpressionLoader(_Loader): def __init__(self, items: type[str]) -> None: self.items: Final = items def load( self, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None, lc: Optional[list[Any]] = None, ) -> Any: if not isinstance(doc, str): raise ValidationException( f"Value is a {convert_typing(extract_type(type(doc)))}, " f"but valid type for this field is a str." ) return doc class _UnionLoader(_Loader): def __init__(self, alternates: Sequence[_Loader], name: Optional[str] = None) -> None: self.alternates = alternates self.name: Final = name def add_loaders(self, loaders: Sequence[_Loader]) -> None: self.alternates = tuple(loader for loader in chain(self.alternates, loaders)) def load( self, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None, lc: Optional[list[Any]] = None, ) -> Any: errors: Final = [] if lc is None: lc = [] for t in self.alternates: try: return t.load(doc, baseuri, loadingOptions, docRoot=docRoot, lc=lc) except ValidationException as e: if isinstance(t, _ArrayLoader) and len(self.alternates) > 1: continue if isinstance(doc, (CommentedMap, dict)): if "class" in doc: if str(doc.get("class")) == str(t): errors.append( ValidationException( f"Object `{baseuri.split('/')[-1]}` is not valid because:", SourceLine(doc, next(iter(doc)), str), [e], ) ) else: if "array" in str(t): continue else: if "id" in doc: id = baseuri.split("/")[-1] + "#" + str(doc.get("id")) if "id" in lc: errors.append( ValidationException( f"checking object `{id}` using `{t}`", SourceLine(lc, "id", str), [e], ) ) else: errors.append( ValidationException( f"checking object `{id}` using `{t}`", SourceLine(lc, doc.get("id"), str), [e], ) ) else: if not isinstance( t, (_PrimitiveLoader) ): # avoids 'tried was {x}' errors errors.append( ValidationException(f"tried `{t}` but", None, [e]) ) else: # avoids "tried but x" and instead returns the values for parsing errors.append(ValidationException("", None, [e])) if isinstance(doc, (CommentedMap, dict)) and "class" in doc: if str(doc.get("class")) not in str(self.alternates): errors.append( ValidationException( "Field `class` contains undefined reference to " + "`" + "/".join(baseuri.split("/")[0:-1]) + "/" + str(doc.get("class")) + "`", SourceLine(doc, "class", str), [], ) ) raise ValidationException("", None, errors, "*") def __repr__(self) -> str: return self.name if self.name is not None else " | ".join(str(a) for a in self.alternates) class _URILoader(_Loader): def __init__( self, inner: _Loader, scoped_id: bool, vocab_term: bool, scoped_ref: Optional[int], no_link_check: Optional[bool], ) -> None: self.inner: Final = inner self.scoped_id: Final = scoped_id self.vocab_term: Final = vocab_term self.scoped_ref: Final = scoped_ref self.no_link_check: Final = no_link_check def load( self, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None, lc: Optional[list[Any]] = None, ) -> Any: if self.no_link_check is not None: loadingOptions = LoadingOptions( copyfrom=loadingOptions, no_link_check=self.no_link_check ) if isinstance(doc, MutableSequence): newdoc: Final = [] for i in doc: if isinstance(i, str): newdoc.append( expand_url( i, baseuri, loadingOptions, self.scoped_id, self.vocab_term, self.scoped_ref, ) ) else: newdoc.append(i) doc = newdoc elif isinstance(doc, str): doc = expand_url( doc, baseuri, loadingOptions, self.scoped_id, self.vocab_term, self.scoped_ref, ) if isinstance(doc, str): if not loadingOptions.no_link_check: errors: Final = [] try: if not loadingOptions.fetcher.check_exists(doc): errors.append( ValidationException(f"contains undefined reference to `{doc}`") ) except ValidationException: pass if len(errors) > 0: raise ValidationException("", None, errors) return self.inner.load(doc, baseuri, loadingOptions, lc=lc) class _TypeDSLLoader(_Loader): def __init__(self, inner: _Loader, refScope: Optional[int], salad_version: str) -> None: self.inner: Final = inner self.refScope: Final = refScope self.salad_version: Final = salad_version def resolve( self, doc: str, baseuri: str, loadingOptions: LoadingOptions, ) -> Union[list[Union[dict[str, Any], str]], dict[str, Any], str]: doc_ = doc optional = False if doc_.endswith("?"): optional = True doc_ = doc_[0:-1] if doc_.endswith("[]"): salad_versions: Final = [int(v) for v in self.salad_version[1:].split(".")] items: Union[list[Union[dict[str, Any], str]], dict[str, Any], str] = "" rest: Final = doc_[0:-2] if salad_versions < [1, 3]: if rest.endswith("[]"): # To show the error message with the original type return doc else: items = expand_url(rest, baseuri, loadingOptions, False, True, self.refScope) else: items = self.resolve(rest, baseuri, loadingOptions) if isinstance(items, str): items = expand_url(items, baseuri, loadingOptions, False, True, self.refScope) expanded: Union[dict[str, Any], str] = {"type": "array", "items": items} else: expanded = expand_url(doc_, baseuri, loadingOptions, False, True, self.refScope) if optional: return ["null", expanded] else: return expanded def load( self, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None, lc: Optional[list[Any]] = None, ) -> Any: if isinstance(doc, MutableSequence): r: Final[list[Any]] = [] for d in doc: if isinstance(d, str): resolved = self.resolve(d, baseuri, loadingOptions) if isinstance(resolved, MutableSequence): for i in resolved: if i not in r: r.append(i) else: if resolved not in r: r.append(resolved) else: r.append(d) doc = r elif isinstance(doc, str): doc = self.resolve(doc, baseuri, loadingOptions) return self.inner.load(doc, baseuri, loadingOptions, lc=lc) class _IdMapLoader(_Loader): def __init__(self, inner: _Loader, mapSubject: str, mapPredicate: Optional[str]) -> None: self.inner: Final = inner self.mapSubject: Final = mapSubject self.mapPredicate: Final = mapPredicate def load( self, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None, lc: Optional[list[Any]] = None, ) -> Any: if isinstance(doc, MutableMapping): r: Final[list[Any]] = [] for k in doc.keys(): val = doc[k] if isinstance(val, CommentedMap): v = copy.copy(val) v.lc.data = val.lc.data v.lc.filename = val.lc.filename v[self.mapSubject] = k r.append(v) elif isinstance(val, MutableMapping): v2 = copy.copy(val) v2[self.mapSubject] = k r.append(v2) else: if self.mapPredicate: v3 = {self.mapPredicate: val} v3[self.mapSubject] = k r.append(v3) else: raise ValidationException("No mapPredicate") doc = r return self.inner.load(doc, baseuri, loadingOptions, lc=lc) def _document_load( loader: _Loader, doc: Union[str, MutableMapping[str, Any], MutableSequence[Any]], baseuri: str, loadingOptions: LoadingOptions, addl_metadata_fields: Optional[MutableSequence[str]] = None, ) -> tuple[Any, LoadingOptions]: if isinstance(doc, str): return _document_load_by_url( loader, loadingOptions.fetcher.urljoin(baseuri, doc), loadingOptions, addl_metadata_fields=addl_metadata_fields, ) if isinstance(doc, MutableMapping): addl_metadata: Final = {} if addl_metadata_fields is not None: for mf in addl_metadata_fields: if mf in doc: addl_metadata[mf] = doc[mf] docuri: Final = baseuri if "$base" in doc: baseuri = doc["$base"] loadingOptions = LoadingOptions( copyfrom=loadingOptions, namespaces=doc.get("$namespaces", None), schemas=doc.get("$schemas", None), baseuri=doc.get("$base", None), addl_metadata=addl_metadata, ) doc2: Final = copy.copy(doc) if "$namespaces" in doc2: doc2.pop("$namespaces") if "$schemas" in doc2: doc2.pop("$schemas") if "$base" in doc2: doc2.pop("$base") if "$graph" in doc2: loadingOptions.idx[baseuri] = ( loader.load(doc2["$graph"], baseuri, loadingOptions), loadingOptions, ) else: loadingOptions.idx[baseuri] = ( loader.load(doc2, baseuri, loadingOptions, docRoot=baseuri), loadingOptions, ) if docuri != baseuri: loadingOptions.idx[docuri] = loadingOptions.idx[baseuri] return loadingOptions.idx[baseuri] if isinstance(doc, MutableSequence): loadingOptions.idx[baseuri] = ( loader.load(doc, baseuri, loadingOptions), loadingOptions, ) return loadingOptions.idx[baseuri] raise ValidationException( "Expected URI string, MutableMapping or MutableSequence, got %s" % type(doc) ) def _document_load_by_url( loader: _Loader, url: str, loadingOptions: LoadingOptions, addl_metadata_fields: Optional[MutableSequence[str]] = None, ) -> tuple[Any, LoadingOptions]: if url in loadingOptions.idx: return loadingOptions.idx[url] doc_url, frg = urldefrag(url) text: Final = loadingOptions.fetcher.fetch_text(doc_url) textIO: Final = StringIO(text) textIO.name = str(doc_url) yaml: Final = yaml_no_ts() result: Final = yaml.load(textIO) add_lc_filename(result, doc_url) loadingOptions = LoadingOptions(copyfrom=loadingOptions, fileuri=doc_url) _document_load( loader, result, doc_url, loadingOptions, addl_metadata_fields=addl_metadata_fields, ) return loadingOptions.idx[url] def file_uri(path: str, split_frag: bool = False) -> str: """Transform a file path into a URL with file scheme.""" if path.startswith("file://"): return path if split_frag: pathsp: Final = path.split("#", 2) frag = "#" + quote(str(pathsp[1])) if len(pathsp) == 2 else "" urlpath = pathname2url(str(pathsp[0])) else: urlpath = pathname2url(path) frag = "" if urlpath.startswith("//"): return f"file:{urlpath}{frag}" return f"file://{urlpath}{frag}" def prefix_url(url: str, namespaces: dict[str, str]) -> str: """Expand short forms into full URLs using the given namespace dictionary.""" for k, v in namespaces.items(): if url.startswith(v): return k + ":" + url[len(v) :] return url def save_relative_uri( uri: Any, base_url: str, scoped_id: bool, ref_scope: Optional[int], relative_uris: bool, ) -> Any: """Convert any URI to a relative one, obeying the scoping rules.""" if isinstance(uri, MutableSequence): return [save_relative_uri(u, base_url, scoped_id, ref_scope, relative_uris) for u in uri] elif isinstance(uri, str): if not relative_uris or uri == base_url: return uri urisplit: Final = urlsplit(uri) basesplit: Final = urlsplit(base_url) if urisplit.scheme == basesplit.scheme and urisplit.netloc == basesplit.netloc: if urisplit.path != basesplit.path: p = os.path.relpath(urisplit.path, os.path.dirname(basesplit.path)) if urisplit.fragment: p = p + "#" + urisplit.fragment return p basefrag = basesplit.fragment + "/" if ref_scope: sp = basefrag.split("/") i = 0 while i < ref_scope: sp.pop() i += 1 basefrag = "/".join(sp) if urisplit.fragment.startswith(basefrag): return urisplit.fragment[len(basefrag) :] return urisplit.fragment return uri else: return save(uri, top=False, base_url=base_url, relative_uris=relative_uris) def shortname(inputid: str) -> str: """ Compute the shortname of a fully qualified identifier. See https://w3id.org/cwl/v1.2/SchemaSalad.html#Short_names. """ parsed_id: Final = urlparse(inputid) if parsed_id.fragment: return parsed_id.fragment.split("/")[-1] return parsed_id.path.split("/")[-1] def parser_info() -> str: return "org.w3id.cwl.v1_2" class Documented(Saveable): pass class RecordField(Documented): """ A field of a record. """ name: str def __init__( self, name: Any, type_: Any, doc: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.doc = doc self.name = name if name is not None else "_:" + str(_uuid__.uuid4()) self.type_ = type_ def __eq__(self, other: Any) -> bool: if isinstance(other, RecordField): return bool( self.doc == other.doc and self.name == other.name and self.type_ == other.type_ ) return False def __hash__(self) -> int: return hash((self.doc, self.name, self.type_)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "RecordField": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] name = None if "name" in _doc: try: name = load_field( _doc.get("name"), uri_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("name") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `name`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("name") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [e], detailed_message=f"the `name` field with value `{val}` " "is not valid because:", ) ) __original_name_is_none = name is None if name is None: if docRoot is not None: name = docRoot else: _errors__.append(ValidationException("missing name")) if not __original_name_is_none: baseuri = cast(str, name) doc = None if "doc" in _doc: try: doc = load_field( _doc.get("doc"), union_of_None_type_or_strtype_or_array_of_strtype, baseuri, loadingOptions, lc=_doc.get("doc") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `doc`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("doc") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [e], detailed_message=f"the `doc` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("type") is None: raise ValidationException("missing required field `type`", None, []) type_ = load_field( _doc.get("type"), typedsl_union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype_or_array_of_union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype_2, baseuri, loadingOptions, lc=_doc.get("type") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `type`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("type") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [e], detailed_message=f"the `type` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `doc`, `name`, `type`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( doc=doc, name=name, type_=type_, extension_fields=extension_fields, loadingOptions=loadingOptions, ) loadingOptions.idx[cast(str, name)] = (_constructed, loadingOptions) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.name is not None: u = save_relative_uri(self.name, base_url, True, None, relative_uris) r["name"] = u if self.doc is not None: r["doc"] = save( self.doc, top=False, base_url=self.name, relative_uris=relative_uris ) if self.type_ is not None: r["type"] = save( self.type_, top=False, base_url=self.name, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["doc", "name", "type"]) class RecordSchema(Saveable): def __init__( self, type_: Any, fields: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.fields = fields self.type_ = type_ def __eq__(self, other: Any) -> bool: if isinstance(other, RecordSchema): return bool(self.fields == other.fields and self.type_ == other.type_) return False def __hash__(self) -> int: return hash((self.fields, self.type_)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "RecordSchema": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] fields = None if "fields" in _doc: try: fields = load_field( _doc.get("fields"), idmap_fields_union_of_None_type_or_array_of_RecordFieldLoader, baseuri, loadingOptions, lc=_doc.get("fields") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `fields`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("fields") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `fields` field is not valid because:", SourceLine(_doc, "fields", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `fields` field is not valid because:", SourceLine(_doc, "fields", str), [e], detailed_message=f"the `fields` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("type") is None: raise ValidationException("missing required field `type`", None, []) type_ = load_field( _doc.get("type"), typedsl_Record_nameLoader_2, baseuri, loadingOptions, lc=_doc.get("type") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `type`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("type") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [e], detailed_message=f"the `type` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `fields`, `type`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( fields=fields, type_=type_, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.fields is not None: r["fields"] = save( self.fields, top=False, base_url=base_url, relative_uris=relative_uris ) if self.type_ is not None: r["type"] = save( self.type_, top=False, base_url=base_url, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["fields", "type"]) class EnumSchema(Saveable): """ Define an enumerated type. """ name: str def __init__( self, symbols: Any, type_: Any, name: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.name = name if name is not None else "_:" + str(_uuid__.uuid4()) self.symbols = symbols self.type_ = type_ def __eq__(self, other: Any) -> bool: if isinstance(other, EnumSchema): return bool( self.name == other.name and self.symbols == other.symbols and self.type_ == other.type_ ) return False def __hash__(self) -> int: return hash((self.name, self.symbols, self.type_)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "EnumSchema": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] name = None if "name" in _doc: try: name = load_field( _doc.get("name"), uri_union_of_None_type_or_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("name") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `name`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("name") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [e], detailed_message=f"the `name` field with value `{val}` " "is not valid because:", ) ) __original_name_is_none = name is None if name is None: if docRoot is not None: name = docRoot else: name = "_:" + str(_uuid__.uuid4()) if not __original_name_is_none: baseuri = cast(str, name) try: if _doc.get("symbols") is None: raise ValidationException("missing required field `symbols`", None, []) symbols = load_field( _doc.get("symbols"), uri_array_of_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("symbols") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `symbols`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("symbols") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `symbols` field is not valid because:", SourceLine(_doc, "symbols", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `symbols` field is not valid because:", SourceLine(_doc, "symbols", str), [e], detailed_message=f"the `symbols` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("type") is None: raise ValidationException("missing required field `type`", None, []) type_ = load_field( _doc.get("type"), typedsl_Enum_nameLoader_2, baseuri, loadingOptions, lc=_doc.get("type") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `type`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("type") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [e], detailed_message=f"the `type` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `name`, `symbols`, `type`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( name=name, symbols=symbols, type_=type_, extension_fields=extension_fields, loadingOptions=loadingOptions, ) loadingOptions.idx[cast(str, name)] = (_constructed, loadingOptions) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.name is not None: u = save_relative_uri(self.name, base_url, True, None, relative_uris) r["name"] = u if self.symbols is not None: u = save_relative_uri(self.symbols, self.name, True, None, relative_uris) r["symbols"] = u if self.type_ is not None: r["type"] = save( self.type_, top=False, base_url=self.name, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["name", "symbols", "type"]) class ArraySchema(Saveable): def __init__( self, items: Any, type_: Any, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.items = items self.type_ = type_ def __eq__(self, other: Any) -> bool: if isinstance(other, ArraySchema): return bool(self.items == other.items and self.type_ == other.type_) return False def __hash__(self) -> int: return hash((self.items, self.type_)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "ArraySchema": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("items") is None: raise ValidationException("missing required field `items`", None, []) items = load_field( _doc.get("items"), uri_union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype_or_array_of_union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype_False_True_2_None, baseuri, loadingOptions, lc=_doc.get("items") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `items`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("items") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `items` field is not valid because:", SourceLine(_doc, "items", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `items` field is not valid because:", SourceLine(_doc, "items", str), [e], detailed_message=f"the `items` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("type") is None: raise ValidationException("missing required field `type`", None, []) type_ = load_field( _doc.get("type"), typedsl_Array_nameLoader_2, baseuri, loadingOptions, lc=_doc.get("type") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `type`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("type") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [e], detailed_message=f"the `type` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `items`, `type`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( items=items, type_=type_, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.items is not None: u = save_relative_uri(self.items, base_url, False, 2, relative_uris) r["items"] = u if self.type_ is not None: r["type"] = save( self.type_, top=False, base_url=base_url, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["items", "type"]) class MapSchema(Saveable): def __init__( self, type_: Any, values: Any, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.type_ = type_ self.values = values def __eq__(self, other: Any) -> bool: if isinstance(other, MapSchema): return bool(self.type_ == other.type_ and self.values == other.values) return False def __hash__(self) -> int: return hash((self.type_, self.values)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "MapSchema": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("type") is None: raise ValidationException("missing required field `type`", None, []) type_ = load_field( _doc.get("type"), typedsl_Map_nameLoader_2, baseuri, loadingOptions, lc=_doc.get("type") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `type`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("type") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [e], detailed_message=f"the `type` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("values") is None: raise ValidationException("missing required field `values`", None, []) values = load_field( _doc.get("values"), uri_union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype_or_array_of_union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype_False_True_2_None, baseuri, loadingOptions, lc=_doc.get("values") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `values`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("values") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `values` field is not valid because:", SourceLine(_doc, "values", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `values` field is not valid because:", SourceLine(_doc, "values", str), [e], detailed_message=f"the `values` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `type`, `values`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( type_=type_, values=values, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.type_ is not None: r["type"] = save( self.type_, top=False, base_url=base_url, relative_uris=relative_uris ) if self.values is not None: u = save_relative_uri(self.values, base_url, False, 2, relative_uris) r["values"] = u # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["type", "values"]) class UnionSchema(Saveable): def __init__( self, names: Any, type_: Any, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.names = names self.type_ = type_ def __eq__(self, other: Any) -> bool: if isinstance(other, UnionSchema): return bool(self.names == other.names and self.type_ == other.type_) return False def __hash__(self) -> int: return hash((self.names, self.type_)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "UnionSchema": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("names") is None: raise ValidationException("missing required field `names`", None, []) names = load_field( _doc.get("names"), uri_union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype_or_array_of_union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype_False_True_2_None, baseuri, loadingOptions, lc=_doc.get("names") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `names`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("names") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `names` field is not valid because:", SourceLine(_doc, "names", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `names` field is not valid because:", SourceLine(_doc, "names", str), [e], detailed_message=f"the `names` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("type") is None: raise ValidationException("missing required field `type`", None, []) type_ = load_field( _doc.get("type"), typedsl_Union_nameLoader_2, baseuri, loadingOptions, lc=_doc.get("type") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `type`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("type") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [e], detailed_message=f"the `type` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `names`, `type`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( names=names, type_=type_, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.names is not None: u = save_relative_uri(self.names, base_url, False, 2, relative_uris) r["names"] = u if self.type_ is not None: r["type"] = save( self.type_, top=False, base_url=base_url, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["names", "type"]) class CWLArraySchema(ArraySchema): def __init__( self, items: Any, type_: Any, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.items = items self.type_ = type_ def __eq__(self, other: Any) -> bool: if isinstance(other, CWLArraySchema): return bool(self.items == other.items and self.type_ == other.type_) return False def __hash__(self) -> int: return hash((self.items, self.type_)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "CWLArraySchema": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("items") is None: raise ValidationException("missing required field `items`", None, []) items = load_field( _doc.get("items"), uri_union_of_PrimitiveTypeLoader_or_CWLRecordSchemaLoader_or_EnumSchemaLoader_or_CWLArraySchemaLoader_or_strtype_or_array_of_union_of_PrimitiveTypeLoader_or_CWLRecordSchemaLoader_or_EnumSchemaLoader_or_CWLArraySchemaLoader_or_strtype_False_True_2_None, baseuri, loadingOptions, lc=_doc.get("items") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `items`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("items") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `items` field is not valid because:", SourceLine(_doc, "items", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `items` field is not valid because:", SourceLine(_doc, "items", str), [e], detailed_message=f"the `items` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("type") is None: raise ValidationException("missing required field `type`", None, []) type_ = load_field( _doc.get("type"), typedsl_Array_nameLoader_2, baseuri, loadingOptions, lc=_doc.get("type") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `type`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("type") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [e], detailed_message=f"the `type` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `items`, `type`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( items=items, type_=type_, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.items is not None: u = save_relative_uri(self.items, base_url, False, 2, relative_uris) r["items"] = u if self.type_ is not None: r["type"] = save( self.type_, top=False, base_url=base_url, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["items", "type"]) class CWLRecordField(RecordField): name: str def __init__( self, name: Any, type_: Any, doc: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.doc = doc self.name = name if name is not None else "_:" + str(_uuid__.uuid4()) self.type_ = type_ def __eq__(self, other: Any) -> bool: if isinstance(other, CWLRecordField): return bool( self.doc == other.doc and self.name == other.name and self.type_ == other.type_ ) return False def __hash__(self) -> int: return hash((self.doc, self.name, self.type_)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "CWLRecordField": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] name = None if "name" in _doc: try: name = load_field( _doc.get("name"), uri_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("name") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `name`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("name") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [e], detailed_message=f"the `name` field with value `{val}` " "is not valid because:", ) ) __original_name_is_none = name is None if name is None: if docRoot is not None: name = docRoot else: _errors__.append(ValidationException("missing name")) if not __original_name_is_none: baseuri = cast(str, name) doc = None if "doc" in _doc: try: doc = load_field( _doc.get("doc"), union_of_None_type_or_strtype_or_array_of_strtype, baseuri, loadingOptions, lc=_doc.get("doc") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `doc`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("doc") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [e], detailed_message=f"the `doc` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("type") is None: raise ValidationException("missing required field `type`", None, []) type_ = load_field( _doc.get("type"), typedsl_union_of_PrimitiveTypeLoader_or_CWLRecordSchemaLoader_or_EnumSchemaLoader_or_CWLArraySchemaLoader_or_strtype_or_array_of_union_of_PrimitiveTypeLoader_or_CWLRecordSchemaLoader_or_EnumSchemaLoader_or_CWLArraySchemaLoader_or_strtype_2, baseuri, loadingOptions, lc=_doc.get("type") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `type`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("type") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [e], detailed_message=f"the `type` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `doc`, `name`, `type`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( doc=doc, name=name, type_=type_, extension_fields=extension_fields, loadingOptions=loadingOptions, ) loadingOptions.idx[cast(str, name)] = (_constructed, loadingOptions) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.name is not None: u = save_relative_uri(self.name, base_url, True, None, relative_uris) r["name"] = u if self.doc is not None: r["doc"] = save( self.doc, top=False, base_url=self.name, relative_uris=relative_uris ) if self.type_ is not None: r["type"] = save( self.type_, top=False, base_url=self.name, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["doc", "name", "type"]) class CWLRecordSchema(RecordSchema): def __init__( self, type_: Any, fields: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.fields = fields self.type_ = type_ def __eq__(self, other: Any) -> bool: if isinstance(other, CWLRecordSchema): return bool(self.fields == other.fields and self.type_ == other.type_) return False def __hash__(self) -> int: return hash((self.fields, self.type_)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "CWLRecordSchema": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] fields = None if "fields" in _doc: try: fields = load_field( _doc.get("fields"), idmap_fields_union_of_None_type_or_array_of_CWLRecordFieldLoader, baseuri, loadingOptions, lc=_doc.get("fields") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `fields`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("fields") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `fields` field is not valid because:", SourceLine(_doc, "fields", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `fields` field is not valid because:", SourceLine(_doc, "fields", str), [e], detailed_message=f"the `fields` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("type") is None: raise ValidationException("missing required field `type`", None, []) type_ = load_field( _doc.get("type"), typedsl_Record_nameLoader_2, baseuri, loadingOptions, lc=_doc.get("type") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `type`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("type") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [e], detailed_message=f"the `type` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `fields`, `type`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( fields=fields, type_=type_, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.fields is not None: r["fields"] = save( self.fields, top=False, base_url=base_url, relative_uris=relative_uris ) if self.type_ is not None: r["type"] = save( self.type_, top=False, base_url=base_url, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["fields", "type"]) class File(Saveable): """ Represents a file (or group of files when `secondaryFiles` is provided) that will be accessible by tools using standard POSIX file system call API such as open(2) and read(2). Files are represented as objects with `class` of `File`. File objects have a number of properties that provide metadata about the file. The `location` property of a File is a IRI that uniquely identifies the file. Implementations must support the `file://` IRI scheme and may support other schemes such as `http://` and `https://`. The value of `location` may also be a relative reference, in which case it must be resolved relative to the IRI of the document it appears in. Alternately to `location`, implementations must also accept the `path` property on File, which must be a filesystem path available on the same host as the CWL runner (for inputs) or the runtime environment of a command line tool execution (for command line tool outputs). If no `location` or `path` is specified, a file object must specify `contents` with the UTF-8 text content of the file. This is a "file literal". File literals do not correspond to external resources, but are created on disk with `contents` with when needed for executing a tool. Where appropriate, expressions can return file literals to define new files on a runtime. The maximum size of `contents` is 64 kilobytes. The `basename` property defines the filename on disk where the file is staged. This may differ from the resource name. If not provided, `basename` must be computed from the last path part of `location` and made available to expressions. The `secondaryFiles` property is a list of File or Directory objects that must be staged in the same directory as the primary file. It is an error for file names to be duplicated in `secondaryFiles`. The `size` property is the size in bytes of the File. It must be computed from the resource and made available to expressions. The `checksum` field contains a cryptographic hash of the file content for use it verifying file contents. Implementations may, at user option, enable or disable computation of the `checksum` field for performance or other reasons. However, the ability to compute output checksums is required to pass the CWL conformance test suite. When executing a CommandLineTool, the files and secondary files may be staged to an arbitrary directory, but must use the value of `basename` for the filename. The `path` property must be file path in the context of the tool execution runtime (local to the compute node, or within the executing container). All computed properties should be available to expressions. File literals also must be staged and `path` must be set. When collecting CommandLineTool outputs, `glob` matching returns file paths (with the `path` property) and the derived properties. This can all be modified by `outputEval`. Alternately, if the file `cwl.output.json` is present in the output, `outputBinding` is ignored. File objects in the output must provide either a `location` IRI or a `path` property in the context of the tool execution runtime (local to the compute node, or within the executing container). When evaluating an ExpressionTool, file objects must be referenced via `location` (the expression tool does not have access to files on disk so `path` is meaningless) or as file literals. It is legal to return a file object with an existing `location` but a different `basename`. The `loadContents` field of ExpressionTool inputs behaves the same as on CommandLineTool inputs, however it is not meaningful on the outputs. An ExpressionTool may forward file references from input to output by using the same value for `location`. """ def __init__( self, location: Optional[Any] = None, path: Optional[Any] = None, basename: Optional[Any] = None, dirname: Optional[Any] = None, nameroot: Optional[Any] = None, nameext: Optional[Any] = None, checksum: Optional[Any] = None, size: Optional[Any] = None, secondaryFiles: Optional[Any] = None, format: Optional[Any] = None, contents: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.class_ = "File" self.location = location self.path = path self.basename = basename self.dirname = dirname self.nameroot = nameroot self.nameext = nameext self.checksum = checksum self.size = size self.secondaryFiles = secondaryFiles self.format = format self.contents = contents def __eq__(self, other: Any) -> bool: if isinstance(other, File): return bool( self.class_ == other.class_ and self.location == other.location and self.path == other.path and self.basename == other.basename and self.dirname == other.dirname and self.nameroot == other.nameroot and self.nameext == other.nameext and self.checksum == other.checksum and self.size == other.size and self.secondaryFiles == other.secondaryFiles and self.format == other.format and self.contents == other.contents ) return False def __hash__(self) -> int: return hash( ( self.class_, self.location, self.path, self.basename, self.dirname, self.nameroot, self.nameext, self.checksum, self.size, self.secondaryFiles, self.format, self.contents, ) ) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "File": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("class") is None: raise ValidationException("missing required field `class`", None, []) class_ = load_field( _doc.get("class"), uri_File_classLoader_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("class") ) if class_ not in (cls.__name__, loadingOptions.vocab.get(cls.__name__)): raise ValidationException(f"tried `{cls.__name__}` but") except ValidationException as e: raise e location = None if "location" in _doc: try: location = load_field( _doc.get("location"), uri_union_of_None_type_or_strtype_False_False_None_None, baseuri, loadingOptions, lc=_doc.get("location") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `location`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("location") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `location` field is not valid because:", SourceLine(_doc, "location", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `location` field is not valid because:", SourceLine(_doc, "location", str), [e], detailed_message=f"the `location` field with value `{val}` " "is not valid because:", ) ) path = None if "path" in _doc: try: path = load_field( _doc.get("path"), uri_union_of_None_type_or_strtype_False_False_None_None, baseuri, loadingOptions, lc=_doc.get("path") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `path`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("path") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `path` field is not valid because:", SourceLine(_doc, "path", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `path` field is not valid because:", SourceLine(_doc, "path", str), [e], detailed_message=f"the `path` field with value `{val}` " "is not valid because:", ) ) basename = None if "basename" in _doc: try: basename = load_field( _doc.get("basename"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("basename") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `basename`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("basename") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `basename` field is not valid because:", SourceLine(_doc, "basename", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `basename` field is not valid because:", SourceLine(_doc, "basename", str), [e], detailed_message=f"the `basename` field with value `{val}` " "is not valid because:", ) ) dirname = None if "dirname" in _doc: try: dirname = load_field( _doc.get("dirname"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("dirname") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `dirname`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("dirname") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `dirname` field is not valid because:", SourceLine(_doc, "dirname", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `dirname` field is not valid because:", SourceLine(_doc, "dirname", str), [e], detailed_message=f"the `dirname` field with value `{val}` " "is not valid because:", ) ) nameroot = None if "nameroot" in _doc: try: nameroot = load_field( _doc.get("nameroot"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("nameroot") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `nameroot`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("nameroot") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `nameroot` field is not valid because:", SourceLine(_doc, "nameroot", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `nameroot` field is not valid because:", SourceLine(_doc, "nameroot", str), [e], detailed_message=f"the `nameroot` field with value `{val}` " "is not valid because:", ) ) nameext = None if "nameext" in _doc: try: nameext = load_field( _doc.get("nameext"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("nameext") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `nameext`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("nameext") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `nameext` field is not valid because:", SourceLine(_doc, "nameext", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `nameext` field is not valid because:", SourceLine(_doc, "nameext", str), [e], detailed_message=f"the `nameext` field with value `{val}` " "is not valid because:", ) ) checksum = None if "checksum" in _doc: try: checksum = load_field( _doc.get("checksum"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("checksum") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `checksum`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("checksum") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `checksum` field is not valid because:", SourceLine(_doc, "checksum", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `checksum` field is not valid because:", SourceLine(_doc, "checksum", str), [e], detailed_message=f"the `checksum` field with value `{val}` " "is not valid because:", ) ) size = None if "size" in _doc: try: size = load_field( _doc.get("size"), union_of_None_type_or_inttype, baseuri, loadingOptions, lc=_doc.get("size") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `size`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("size") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `size` field is not valid because:", SourceLine(_doc, "size", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `size` field is not valid because:", SourceLine(_doc, "size", str), [e], detailed_message=f"the `size` field with value `{val}` " "is not valid because:", ) ) secondaryFiles = None if "secondaryFiles" in _doc: try: secondaryFiles = load_field( _doc.get("secondaryFiles"), secondaryfilesdsl_union_of_None_type_or_array_of_union_of_FileLoader_or_DirectoryLoader, baseuri, loadingOptions, lc=_doc.get("secondaryFiles") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `secondaryFiles`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("secondaryFiles") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `secondaryFiles` field is not valid because:", SourceLine(_doc, "secondaryFiles", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `secondaryFiles` field is not valid because:", SourceLine(_doc, "secondaryFiles", str), [e], detailed_message=f"the `secondaryFiles` field with value `{val}` " "is not valid because:", ) ) format = None if "format" in _doc: try: format = load_field( _doc.get("format"), uri_union_of_None_type_or_strtype_True_False_None_True, baseuri, loadingOptions, lc=_doc.get("format") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `format`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("format") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `format` field is not valid because:", SourceLine(_doc, "format", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `format` field is not valid because:", SourceLine(_doc, "format", str), [e], detailed_message=f"the `format` field with value `{val}` " "is not valid because:", ) ) contents = None if "contents" in _doc: try: contents = load_field( _doc.get("contents"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("contents") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `contents`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("contents") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `contents` field is not valid because:", SourceLine(_doc, "contents", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `contents` field is not valid because:", SourceLine(_doc, "contents", str), [e], detailed_message=f"the `contents` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `class`, `location`, `path`, `basename`, `dirname`, `nameroot`, `nameext`, `checksum`, `size`, `secondaryFiles`, `format`, `contents`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( location=location, path=path, basename=basename, dirname=dirname, nameroot=nameroot, nameext=nameext, checksum=checksum, size=size, secondaryFiles=secondaryFiles, format=format, contents=contents, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.class_ is not None: uri = self.loadingOptions.vocab[self.class_] if p := self.loadingOptions.rvocab.get(uri[: -len(self.class_)]): uri = f"{p}:{self.class_}" else: uri = self.class_ u = save_relative_uri(uri, base_url, False, None, relative_uris) r["class"] = u if self.location is not None: u = save_relative_uri(self.location, base_url, False, None, relative_uris) r["location"] = u if self.path is not None: u = save_relative_uri(self.path, base_url, False, None, relative_uris) r["path"] = u if self.basename is not None: r["basename"] = save( self.basename, top=False, base_url=base_url, relative_uris=relative_uris ) if self.dirname is not None: r["dirname"] = save( self.dirname, top=False, base_url=base_url, relative_uris=relative_uris ) if self.nameroot is not None: r["nameroot"] = save( self.nameroot, top=False, base_url=base_url, relative_uris=relative_uris ) if self.nameext is not None: r["nameext"] = save( self.nameext, top=False, base_url=base_url, relative_uris=relative_uris ) if self.checksum is not None: r["checksum"] = save( self.checksum, top=False, base_url=base_url, relative_uris=relative_uris ) if self.size is not None: r["size"] = save( self.size, top=False, base_url=base_url, relative_uris=relative_uris ) if self.secondaryFiles is not None: r["secondaryFiles"] = save( self.secondaryFiles, top=False, base_url=base_url, relative_uris=relative_uris, ) if self.format is not None: u = save_relative_uri(self.format, base_url, True, None, relative_uris) r["format"] = u if self.contents is not None: r["contents"] = save( self.contents, top=False, base_url=base_url, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset( [ "class", "location", "path", "basename", "dirname", "nameroot", "nameext", "checksum", "size", "secondaryFiles", "format", "contents", ] ) class Directory(Saveable): """ Represents a directory to present to a command line tool. Directories are represented as objects with `class` of `Directory`. Directory objects have a number of properties that provide metadata about the directory. The `location` property of a Directory is a IRI that uniquely identifies the directory. Implementations must support the file:// IRI scheme and may support other schemes such as http://. Alternately to `location`, implementations must also accept the `path` property on Directory, which must be a filesystem path available on the same host as the CWL runner (for inputs) or the runtime environment of a command line tool execution (for command line tool outputs). A Directory object may have a `listing` field. This is a list of File and Directory objects that are contained in the Directory. For each entry in `listing`, the `basename` property defines the name of the File or Subdirectory when staged to disk. If `listing` is not provided, the implementation must have some way of fetching the Directory listing at runtime based on the `location` field. If a Directory does not have `location`, it is a Directory literal. A Directory literal must provide `listing`. Directory literals must be created on disk at runtime as needed. The resources in a Directory literal do not need to have any implied relationship in their `location`. For example, a Directory listing may contain two files located on different hosts. It is the responsibility of the runtime to ensure that those files are staged to disk appropriately. Secondary files associated with files in `listing` must also be staged to the same Directory. When executing a CommandLineTool, Directories must be recursively staged first and have local values of `path` assigned. Directory objects in CommandLineTool output must provide either a `location` IRI or a `path` property in the context of the tool execution runtime (local to the compute node, or within the executing container). An ExpressionTool may forward file references from input to output by using the same value for `location`. Name conflicts (the same `basename` appearing multiple times in `listing` or in any entry in `secondaryFiles` in the listing) is a fatal error. """ def __init__( self, location: Optional[Any] = None, path: Optional[Any] = None, basename: Optional[Any] = None, listing: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.class_ = "Directory" self.location = location self.path = path self.basename = basename self.listing = listing def __eq__(self, other: Any) -> bool: if isinstance(other, Directory): return bool( self.class_ == other.class_ and self.location == other.location and self.path == other.path and self.basename == other.basename and self.listing == other.listing ) return False def __hash__(self) -> int: return hash( (self.class_, self.location, self.path, self.basename, self.listing) ) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "Directory": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("class") is None: raise ValidationException("missing required field `class`", None, []) class_ = load_field( _doc.get("class"), uri_Directory_classLoader_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("class") ) if class_ not in (cls.__name__, loadingOptions.vocab.get(cls.__name__)): raise ValidationException(f"tried `{cls.__name__}` but") except ValidationException as e: raise e location = None if "location" in _doc: try: location = load_field( _doc.get("location"), uri_union_of_None_type_or_strtype_False_False_None_None, baseuri, loadingOptions, lc=_doc.get("location") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `location`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("location") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `location` field is not valid because:", SourceLine(_doc, "location", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `location` field is not valid because:", SourceLine(_doc, "location", str), [e], detailed_message=f"the `location` field with value `{val}` " "is not valid because:", ) ) path = None if "path" in _doc: try: path = load_field( _doc.get("path"), uri_union_of_None_type_or_strtype_False_False_None_None, baseuri, loadingOptions, lc=_doc.get("path") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `path`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("path") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `path` field is not valid because:", SourceLine(_doc, "path", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `path` field is not valid because:", SourceLine(_doc, "path", str), [e], detailed_message=f"the `path` field with value `{val}` " "is not valid because:", ) ) basename = None if "basename" in _doc: try: basename = load_field( _doc.get("basename"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("basename") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `basename`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("basename") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `basename` field is not valid because:", SourceLine(_doc, "basename", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `basename` field is not valid because:", SourceLine(_doc, "basename", str), [e], detailed_message=f"the `basename` field with value `{val}` " "is not valid because:", ) ) listing = None if "listing" in _doc: try: listing = load_field( _doc.get("listing"), union_of_None_type_or_array_of_union_of_FileLoader_or_DirectoryLoader, baseuri, loadingOptions, lc=_doc.get("listing") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `listing`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("listing") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `listing` field is not valid because:", SourceLine(_doc, "listing", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `listing` field is not valid because:", SourceLine(_doc, "listing", str), [e], detailed_message=f"the `listing` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `class`, `location`, `path`, `basename`, `listing`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( location=location, path=path, basename=basename, listing=listing, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.class_ is not None: uri = self.loadingOptions.vocab[self.class_] if p := self.loadingOptions.rvocab.get(uri[: -len(self.class_)]): uri = f"{p}:{self.class_}" else: uri = self.class_ u = save_relative_uri(uri, base_url, False, None, relative_uris) r["class"] = u if self.location is not None: u = save_relative_uri(self.location, base_url, False, None, relative_uris) r["location"] = u if self.path is not None: u = save_relative_uri(self.path, base_url, False, None, relative_uris) r["path"] = u if self.basename is not None: r["basename"] = save( self.basename, top=False, base_url=base_url, relative_uris=relative_uris ) if self.listing is not None: r["listing"] = save( self.listing, top=False, base_url=base_url, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["class", "location", "path", "basename", "listing"]) class Labeled(Saveable): pass class Identified(Saveable): pass class IdentifierRequired(Identified): pass class LoadContents(Saveable): pass class FieldBase(Labeled): pass class InputFormat(Saveable): pass class OutputFormat(Saveable): pass class Parameter(FieldBase, Documented, IdentifierRequired): """ Define an input or output parameter to a process. """ pass class InputBinding(Saveable): def __init__( self, loadContents: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.loadContents = loadContents def __eq__(self, other: Any) -> bool: if isinstance(other, InputBinding): return bool(self.loadContents == other.loadContents) return False def __hash__(self) -> int: return hash((self.loadContents)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "InputBinding": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] loadContents = None if "loadContents" in _doc: try: loadContents = load_field( _doc.get("loadContents"), union_of_None_type_or_booltype, baseuri, loadingOptions, lc=_doc.get("loadContents") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `loadContents`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("loadContents") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `loadContents` field is not valid because:", SourceLine(_doc, "loadContents", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `loadContents` field is not valid because:", SourceLine(_doc, "loadContents", str), [e], detailed_message=f"the `loadContents` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `loadContents`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( loadContents=loadContents, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.loadContents is not None: r["loadContents"] = save( self.loadContents, top=False, base_url=base_url, relative_uris=relative_uris, ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["loadContents"]) class IOSchema(Labeled, Documented): pass class InputSchema(IOSchema): pass class OutputSchema(IOSchema): pass class InputRecordField(CWLRecordField, FieldBase, InputFormat, LoadContents): name: str def __init__( self, name: Any, type_: Any, doc: Optional[Any] = None, label: Optional[Any] = None, secondaryFiles: Optional[Any] = None, streamable: Optional[Any] = None, format: Optional[Any] = None, loadContents: Optional[Any] = None, loadListing: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.doc = doc self.name = name if name is not None else "_:" + str(_uuid__.uuid4()) self.type_ = type_ self.label = label self.secondaryFiles = secondaryFiles self.streamable = streamable self.format = format self.loadContents = loadContents self.loadListing = loadListing def __eq__(self, other: Any) -> bool: if isinstance(other, InputRecordField): return bool( self.doc == other.doc and self.name == other.name and self.type_ == other.type_ and self.label == other.label and self.secondaryFiles == other.secondaryFiles and self.streamable == other.streamable and self.format == other.format and self.loadContents == other.loadContents and self.loadListing == other.loadListing ) return False def __hash__(self) -> int: return hash( ( self.doc, self.name, self.type_, self.label, self.secondaryFiles, self.streamable, self.format, self.loadContents, self.loadListing, ) ) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "InputRecordField": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] name = None if "name" in _doc: try: name = load_field( _doc.get("name"), uri_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("name") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `name`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("name") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [e], detailed_message=f"the `name` field with value `{val}` " "is not valid because:", ) ) __original_name_is_none = name is None if name is None: if docRoot is not None: name = docRoot else: _errors__.append(ValidationException("missing name")) if not __original_name_is_none: baseuri = cast(str, name) doc = None if "doc" in _doc: try: doc = load_field( _doc.get("doc"), union_of_None_type_or_strtype_or_array_of_strtype, baseuri, loadingOptions, lc=_doc.get("doc") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `doc`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("doc") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [e], detailed_message=f"the `doc` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("type") is None: raise ValidationException("missing required field `type`", None, []) type_ = load_field( _doc.get("type"), typedsl_union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype_2, baseuri, loadingOptions, lc=_doc.get("type") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `type`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("type") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [e], detailed_message=f"the `type` field with value `{val}` " "is not valid because:", ) ) label = None if "label" in _doc: try: label = load_field( _doc.get("label"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("label") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `label`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("label") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [e], detailed_message=f"the `label` field with value `{val}` " "is not valid because:", ) ) secondaryFiles = None if "secondaryFiles" in _doc: try: secondaryFiles = load_field( _doc.get("secondaryFiles"), secondaryfilesdsl_union_of_None_type_or_SecondaryFileSchemaLoader_or_array_of_SecondaryFileSchemaLoader, baseuri, loadingOptions, lc=_doc.get("secondaryFiles") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `secondaryFiles`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("secondaryFiles") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `secondaryFiles` field is not valid because:", SourceLine(_doc, "secondaryFiles", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `secondaryFiles` field is not valid because:", SourceLine(_doc, "secondaryFiles", str), [e], detailed_message=f"the `secondaryFiles` field with value `{val}` " "is not valid because:", ) ) streamable = None if "streamable" in _doc: try: streamable = load_field( _doc.get("streamable"), union_of_None_type_or_booltype, baseuri, loadingOptions, lc=_doc.get("streamable") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `streamable`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("streamable") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `streamable` field is not valid because:", SourceLine(_doc, "streamable", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `streamable` field is not valid because:", SourceLine(_doc, "streamable", str), [e], detailed_message=f"the `streamable` field with value `{val}` " "is not valid because:", ) ) format = None if "format" in _doc: try: format = load_field( _doc.get("format"), uri_union_of_None_type_or_strtype_or_array_of_strtype_or_ExpressionLoader_True_False_None_True, baseuri, loadingOptions, lc=_doc.get("format") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `format`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("format") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `format` field is not valid because:", SourceLine(_doc, "format", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `format` field is not valid because:", SourceLine(_doc, "format", str), [e], detailed_message=f"the `format` field with value `{val}` " "is not valid because:", ) ) loadContents = None if "loadContents" in _doc: try: loadContents = load_field( _doc.get("loadContents"), union_of_None_type_or_booltype, baseuri, loadingOptions, lc=_doc.get("loadContents") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `loadContents`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("loadContents") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `loadContents` field is not valid because:", SourceLine(_doc, "loadContents", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `loadContents` field is not valid because:", SourceLine(_doc, "loadContents", str), [e], detailed_message=f"the `loadContents` field with value `{val}` " "is not valid because:", ) ) loadListing = None if "loadListing" in _doc: try: loadListing = load_field( _doc.get("loadListing"), union_of_None_type_or_LoadListingEnumLoader, baseuri, loadingOptions, lc=_doc.get("loadListing") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `loadListing`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("loadListing") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `loadListing` field is not valid because:", SourceLine(_doc, "loadListing", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `loadListing` field is not valid because:", SourceLine(_doc, "loadListing", str), [e], detailed_message=f"the `loadListing` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `doc`, `name`, `type`, `label`, `secondaryFiles`, `streamable`, `format`, `loadContents`, `loadListing`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( doc=doc, name=name, type_=type_, label=label, secondaryFiles=secondaryFiles, streamable=streamable, format=format, loadContents=loadContents, loadListing=loadListing, extension_fields=extension_fields, loadingOptions=loadingOptions, ) loadingOptions.idx[cast(str, name)] = (_constructed, loadingOptions) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.name is not None: u = save_relative_uri(self.name, base_url, True, None, relative_uris) r["name"] = u if self.doc is not None: r["doc"] = save( self.doc, top=False, base_url=self.name, relative_uris=relative_uris ) if self.type_ is not None: r["type"] = save( self.type_, top=False, base_url=self.name, relative_uris=relative_uris ) if self.label is not None: r["label"] = save( self.label, top=False, base_url=self.name, relative_uris=relative_uris ) if self.secondaryFiles is not None: r["secondaryFiles"] = save( self.secondaryFiles, top=False, base_url=self.name, relative_uris=relative_uris, ) if self.streamable is not None: r["streamable"] = save( self.streamable, top=False, base_url=self.name, relative_uris=relative_uris, ) if self.format is not None: u = save_relative_uri(self.format, self.name, True, None, relative_uris) r["format"] = u if self.loadContents is not None: r["loadContents"] = save( self.loadContents, top=False, base_url=self.name, relative_uris=relative_uris, ) if self.loadListing is not None: r["loadListing"] = save( self.loadListing, top=False, base_url=self.name, relative_uris=relative_uris, ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset( [ "doc", "name", "type", "label", "secondaryFiles", "streamable", "format", "loadContents", "loadListing", ] ) class InputRecordSchema(CWLRecordSchema, InputSchema): name: str def __init__( self, type_: Any, fields: Optional[Any] = None, label: Optional[Any] = None, doc: Optional[Any] = None, name: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.fields = fields self.type_ = type_ self.label = label self.doc = doc self.name = name if name is not None else "_:" + str(_uuid__.uuid4()) def __eq__(self, other: Any) -> bool: if isinstance(other, InputRecordSchema): return bool( self.fields == other.fields and self.type_ == other.type_ and self.label == other.label and self.doc == other.doc and self.name == other.name ) return False def __hash__(self) -> int: return hash((self.fields, self.type_, self.label, self.doc, self.name)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "InputRecordSchema": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] name = None if "name" in _doc: try: name = load_field( _doc.get("name"), uri_union_of_None_type_or_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("name") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `name`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("name") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [e], detailed_message=f"the `name` field with value `{val}` " "is not valid because:", ) ) __original_name_is_none = name is None if name is None: if docRoot is not None: name = docRoot else: name = "_:" + str(_uuid__.uuid4()) if not __original_name_is_none: baseuri = cast(str, name) fields = None if "fields" in _doc: try: fields = load_field( _doc.get("fields"), idmap_fields_union_of_None_type_or_array_of_InputRecordFieldLoader, baseuri, loadingOptions, lc=_doc.get("fields") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `fields`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("fields") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `fields` field is not valid because:", SourceLine(_doc, "fields", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `fields` field is not valid because:", SourceLine(_doc, "fields", str), [e], detailed_message=f"the `fields` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("type") is None: raise ValidationException("missing required field `type`", None, []) type_ = load_field( _doc.get("type"), typedsl_Record_nameLoader_2, baseuri, loadingOptions, lc=_doc.get("type") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `type`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("type") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [e], detailed_message=f"the `type` field with value `{val}` " "is not valid because:", ) ) label = None if "label" in _doc: try: label = load_field( _doc.get("label"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("label") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `label`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("label") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [e], detailed_message=f"the `label` field with value `{val}` " "is not valid because:", ) ) doc = None if "doc" in _doc: try: doc = load_field( _doc.get("doc"), union_of_None_type_or_strtype_or_array_of_strtype, baseuri, loadingOptions, lc=_doc.get("doc") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `doc`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("doc") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [e], detailed_message=f"the `doc` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `fields`, `type`, `label`, `doc`, `name`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( fields=fields, type_=type_, label=label, doc=doc, name=name, extension_fields=extension_fields, loadingOptions=loadingOptions, ) loadingOptions.idx[cast(str, name)] = (_constructed, loadingOptions) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.name is not None: u = save_relative_uri(self.name, base_url, True, None, relative_uris) r["name"] = u if self.fields is not None: r["fields"] = save( self.fields, top=False, base_url=self.name, relative_uris=relative_uris ) if self.type_ is not None: r["type"] = save( self.type_, top=False, base_url=self.name, relative_uris=relative_uris ) if self.label is not None: r["label"] = save( self.label, top=False, base_url=self.name, relative_uris=relative_uris ) if self.doc is not None: r["doc"] = save( self.doc, top=False, base_url=self.name, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["fields", "type", "label", "doc", "name"]) class InputEnumSchema(EnumSchema, InputSchema): name: str def __init__( self, symbols: Any, type_: Any, name: Optional[Any] = None, label: Optional[Any] = None, doc: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.name = name if name is not None else "_:" + str(_uuid__.uuid4()) self.symbols = symbols self.type_ = type_ self.label = label self.doc = doc def __eq__(self, other: Any) -> bool: if isinstance(other, InputEnumSchema): return bool( self.name == other.name and self.symbols == other.symbols and self.type_ == other.type_ and self.label == other.label and self.doc == other.doc ) return False def __hash__(self) -> int: return hash((self.name, self.symbols, self.type_, self.label, self.doc)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "InputEnumSchema": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] name = None if "name" in _doc: try: name = load_field( _doc.get("name"), uri_union_of_None_type_or_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("name") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `name`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("name") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [e], detailed_message=f"the `name` field with value `{val}` " "is not valid because:", ) ) __original_name_is_none = name is None if name is None: if docRoot is not None: name = docRoot else: name = "_:" + str(_uuid__.uuid4()) if not __original_name_is_none: baseuri = cast(str, name) try: if _doc.get("symbols") is None: raise ValidationException("missing required field `symbols`", None, []) symbols = load_field( _doc.get("symbols"), uri_array_of_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("symbols") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `symbols`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("symbols") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `symbols` field is not valid because:", SourceLine(_doc, "symbols", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `symbols` field is not valid because:", SourceLine(_doc, "symbols", str), [e], detailed_message=f"the `symbols` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("type") is None: raise ValidationException("missing required field `type`", None, []) type_ = load_field( _doc.get("type"), typedsl_Enum_nameLoader_2, baseuri, loadingOptions, lc=_doc.get("type") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `type`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("type") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [e], detailed_message=f"the `type` field with value `{val}` " "is not valid because:", ) ) label = None if "label" in _doc: try: label = load_field( _doc.get("label"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("label") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `label`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("label") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [e], detailed_message=f"the `label` field with value `{val}` " "is not valid because:", ) ) doc = None if "doc" in _doc: try: doc = load_field( _doc.get("doc"), union_of_None_type_or_strtype_or_array_of_strtype, baseuri, loadingOptions, lc=_doc.get("doc") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `doc`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("doc") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [e], detailed_message=f"the `doc` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `name`, `symbols`, `type`, `label`, `doc`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( name=name, symbols=symbols, type_=type_, label=label, doc=doc, extension_fields=extension_fields, loadingOptions=loadingOptions, ) loadingOptions.idx[cast(str, name)] = (_constructed, loadingOptions) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.name is not None: u = save_relative_uri(self.name, base_url, True, None, relative_uris) r["name"] = u if self.symbols is not None: u = save_relative_uri(self.symbols, self.name, True, None, relative_uris) r["symbols"] = u if self.type_ is not None: r["type"] = save( self.type_, top=False, base_url=self.name, relative_uris=relative_uris ) if self.label is not None: r["label"] = save( self.label, top=False, base_url=self.name, relative_uris=relative_uris ) if self.doc is not None: r["doc"] = save( self.doc, top=False, base_url=self.name, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["name", "symbols", "type", "label", "doc"]) class InputArraySchema(CWLArraySchema, InputSchema): name: str def __init__( self, items: Any, type_: Any, label: Optional[Any] = None, doc: Optional[Any] = None, name: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.items = items self.type_ = type_ self.label = label self.doc = doc self.name = name if name is not None else "_:" + str(_uuid__.uuid4()) def __eq__(self, other: Any) -> bool: if isinstance(other, InputArraySchema): return bool( self.items == other.items and self.type_ == other.type_ and self.label == other.label and self.doc == other.doc and self.name == other.name ) return False def __hash__(self) -> int: return hash((self.items, self.type_, self.label, self.doc, self.name)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "InputArraySchema": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] name = None if "name" in _doc: try: name = load_field( _doc.get("name"), uri_union_of_None_type_or_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("name") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `name`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("name") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [e], detailed_message=f"the `name` field with value `{val}` " "is not valid because:", ) ) __original_name_is_none = name is None if name is None: if docRoot is not None: name = docRoot else: name = "_:" + str(_uuid__.uuid4()) if not __original_name_is_none: baseuri = cast(str, name) try: if _doc.get("items") is None: raise ValidationException("missing required field `items`", None, []) items = load_field( _doc.get("items"), uri_union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype_False_True_2_None, baseuri, loadingOptions, lc=_doc.get("items") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `items`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("items") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `items` field is not valid because:", SourceLine(_doc, "items", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `items` field is not valid because:", SourceLine(_doc, "items", str), [e], detailed_message=f"the `items` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("type") is None: raise ValidationException("missing required field `type`", None, []) type_ = load_field( _doc.get("type"), typedsl_Array_nameLoader_2, baseuri, loadingOptions, lc=_doc.get("type") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `type`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("type") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [e], detailed_message=f"the `type` field with value `{val}` " "is not valid because:", ) ) label = None if "label" in _doc: try: label = load_field( _doc.get("label"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("label") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `label`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("label") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [e], detailed_message=f"the `label` field with value `{val}` " "is not valid because:", ) ) doc = None if "doc" in _doc: try: doc = load_field( _doc.get("doc"), union_of_None_type_or_strtype_or_array_of_strtype, baseuri, loadingOptions, lc=_doc.get("doc") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `doc`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("doc") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [e], detailed_message=f"the `doc` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `items`, `type`, `label`, `doc`, `name`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( items=items, type_=type_, label=label, doc=doc, name=name, extension_fields=extension_fields, loadingOptions=loadingOptions, ) loadingOptions.idx[cast(str, name)] = (_constructed, loadingOptions) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.name is not None: u = save_relative_uri(self.name, base_url, True, None, relative_uris) r["name"] = u if self.items is not None: u = save_relative_uri(self.items, self.name, False, 2, relative_uris) r["items"] = u if self.type_ is not None: r["type"] = save( self.type_, top=False, base_url=self.name, relative_uris=relative_uris ) if self.label is not None: r["label"] = save( self.label, top=False, base_url=self.name, relative_uris=relative_uris ) if self.doc is not None: r["doc"] = save( self.doc, top=False, base_url=self.name, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["items", "type", "label", "doc", "name"]) class OutputRecordField(CWLRecordField, FieldBase, OutputFormat): name: str def __init__( self, name: Any, type_: Any, doc: Optional[Any] = None, label: Optional[Any] = None, secondaryFiles: Optional[Any] = None, streamable: Optional[Any] = None, format: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.doc = doc self.name = name if name is not None else "_:" + str(_uuid__.uuid4()) self.type_ = type_ self.label = label self.secondaryFiles = secondaryFiles self.streamable = streamable self.format = format def __eq__(self, other: Any) -> bool: if isinstance(other, OutputRecordField): return bool( self.doc == other.doc and self.name == other.name and self.type_ == other.type_ and self.label == other.label and self.secondaryFiles == other.secondaryFiles and self.streamable == other.streamable and self.format == other.format ) return False def __hash__(self) -> int: return hash( ( self.doc, self.name, self.type_, self.label, self.secondaryFiles, self.streamable, self.format, ) ) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "OutputRecordField": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] name = None if "name" in _doc: try: name = load_field( _doc.get("name"), uri_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("name") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `name`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("name") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [e], detailed_message=f"the `name` field with value `{val}` " "is not valid because:", ) ) __original_name_is_none = name is None if name is None: if docRoot is not None: name = docRoot else: _errors__.append(ValidationException("missing name")) if not __original_name_is_none: baseuri = cast(str, name) doc = None if "doc" in _doc: try: doc = load_field( _doc.get("doc"), union_of_None_type_or_strtype_or_array_of_strtype, baseuri, loadingOptions, lc=_doc.get("doc") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `doc`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("doc") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [e], detailed_message=f"the `doc` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("type") is None: raise ValidationException("missing required field `type`", None, []) type_ = load_field( _doc.get("type"), typedsl_union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype_2, baseuri, loadingOptions, lc=_doc.get("type") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `type`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("type") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [e], detailed_message=f"the `type` field with value `{val}` " "is not valid because:", ) ) label = None if "label" in _doc: try: label = load_field( _doc.get("label"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("label") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `label`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("label") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [e], detailed_message=f"the `label` field with value `{val}` " "is not valid because:", ) ) secondaryFiles = None if "secondaryFiles" in _doc: try: secondaryFiles = load_field( _doc.get("secondaryFiles"), secondaryfilesdsl_union_of_None_type_or_SecondaryFileSchemaLoader_or_array_of_SecondaryFileSchemaLoader, baseuri, loadingOptions, lc=_doc.get("secondaryFiles") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `secondaryFiles`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("secondaryFiles") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `secondaryFiles` field is not valid because:", SourceLine(_doc, "secondaryFiles", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `secondaryFiles` field is not valid because:", SourceLine(_doc, "secondaryFiles", str), [e], detailed_message=f"the `secondaryFiles` field with value `{val}` " "is not valid because:", ) ) streamable = None if "streamable" in _doc: try: streamable = load_field( _doc.get("streamable"), union_of_None_type_or_booltype, baseuri, loadingOptions, lc=_doc.get("streamable") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `streamable`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("streamable") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `streamable` field is not valid because:", SourceLine(_doc, "streamable", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `streamable` field is not valid because:", SourceLine(_doc, "streamable", str), [e], detailed_message=f"the `streamable` field with value `{val}` " "is not valid because:", ) ) format = None if "format" in _doc: try: format = load_field( _doc.get("format"), uri_union_of_None_type_or_strtype_or_ExpressionLoader_True_False_None_True, baseuri, loadingOptions, lc=_doc.get("format") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `format`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("format") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `format` field is not valid because:", SourceLine(_doc, "format", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `format` field is not valid because:", SourceLine(_doc, "format", str), [e], detailed_message=f"the `format` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `doc`, `name`, `type`, `label`, `secondaryFiles`, `streamable`, `format`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( doc=doc, name=name, type_=type_, label=label, secondaryFiles=secondaryFiles, streamable=streamable, format=format, extension_fields=extension_fields, loadingOptions=loadingOptions, ) loadingOptions.idx[cast(str, name)] = (_constructed, loadingOptions) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.name is not None: u = save_relative_uri(self.name, base_url, True, None, relative_uris) r["name"] = u if self.doc is not None: r["doc"] = save( self.doc, top=False, base_url=self.name, relative_uris=relative_uris ) if self.type_ is not None: r["type"] = save( self.type_, top=False, base_url=self.name, relative_uris=relative_uris ) if self.label is not None: r["label"] = save( self.label, top=False, base_url=self.name, relative_uris=relative_uris ) if self.secondaryFiles is not None: r["secondaryFiles"] = save( self.secondaryFiles, top=False, base_url=self.name, relative_uris=relative_uris, ) if self.streamable is not None: r["streamable"] = save( self.streamable, top=False, base_url=self.name, relative_uris=relative_uris, ) if self.format is not None: u = save_relative_uri(self.format, self.name, True, None, relative_uris) r["format"] = u # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset( ["doc", "name", "type", "label", "secondaryFiles", "streamable", "format"] ) class OutputRecordSchema(CWLRecordSchema, OutputSchema): name: str def __init__( self, type_: Any, fields: Optional[Any] = None, label: Optional[Any] = None, doc: Optional[Any] = None, name: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.fields = fields self.type_ = type_ self.label = label self.doc = doc self.name = name if name is not None else "_:" + str(_uuid__.uuid4()) def __eq__(self, other: Any) -> bool: if isinstance(other, OutputRecordSchema): return bool( self.fields == other.fields and self.type_ == other.type_ and self.label == other.label and self.doc == other.doc and self.name == other.name ) return False def __hash__(self) -> int: return hash((self.fields, self.type_, self.label, self.doc, self.name)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "OutputRecordSchema": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] name = None if "name" in _doc: try: name = load_field( _doc.get("name"), uri_union_of_None_type_or_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("name") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `name`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("name") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [e], detailed_message=f"the `name` field with value `{val}` " "is not valid because:", ) ) __original_name_is_none = name is None if name is None: if docRoot is not None: name = docRoot else: name = "_:" + str(_uuid__.uuid4()) if not __original_name_is_none: baseuri = cast(str, name) fields = None if "fields" in _doc: try: fields = load_field( _doc.get("fields"), idmap_fields_union_of_None_type_or_array_of_OutputRecordFieldLoader, baseuri, loadingOptions, lc=_doc.get("fields") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `fields`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("fields") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `fields` field is not valid because:", SourceLine(_doc, "fields", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `fields` field is not valid because:", SourceLine(_doc, "fields", str), [e], detailed_message=f"the `fields` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("type") is None: raise ValidationException("missing required field `type`", None, []) type_ = load_field( _doc.get("type"), typedsl_Record_nameLoader_2, baseuri, loadingOptions, lc=_doc.get("type") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `type`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("type") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [e], detailed_message=f"the `type` field with value `{val}` " "is not valid because:", ) ) label = None if "label" in _doc: try: label = load_field( _doc.get("label"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("label") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `label`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("label") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [e], detailed_message=f"the `label` field with value `{val}` " "is not valid because:", ) ) doc = None if "doc" in _doc: try: doc = load_field( _doc.get("doc"), union_of_None_type_or_strtype_or_array_of_strtype, baseuri, loadingOptions, lc=_doc.get("doc") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `doc`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("doc") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [e], detailed_message=f"the `doc` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `fields`, `type`, `label`, `doc`, `name`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( fields=fields, type_=type_, label=label, doc=doc, name=name, extension_fields=extension_fields, loadingOptions=loadingOptions, ) loadingOptions.idx[cast(str, name)] = (_constructed, loadingOptions) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.name is not None: u = save_relative_uri(self.name, base_url, True, None, relative_uris) r["name"] = u if self.fields is not None: r["fields"] = save( self.fields, top=False, base_url=self.name, relative_uris=relative_uris ) if self.type_ is not None: r["type"] = save( self.type_, top=False, base_url=self.name, relative_uris=relative_uris ) if self.label is not None: r["label"] = save( self.label, top=False, base_url=self.name, relative_uris=relative_uris ) if self.doc is not None: r["doc"] = save( self.doc, top=False, base_url=self.name, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["fields", "type", "label", "doc", "name"]) class OutputEnumSchema(EnumSchema, OutputSchema): name: str def __init__( self, symbols: Any, type_: Any, name: Optional[Any] = None, label: Optional[Any] = None, doc: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.name = name if name is not None else "_:" + str(_uuid__.uuid4()) self.symbols = symbols self.type_ = type_ self.label = label self.doc = doc def __eq__(self, other: Any) -> bool: if isinstance(other, OutputEnumSchema): return bool( self.name == other.name and self.symbols == other.symbols and self.type_ == other.type_ and self.label == other.label and self.doc == other.doc ) return False def __hash__(self) -> int: return hash((self.name, self.symbols, self.type_, self.label, self.doc)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "OutputEnumSchema": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] name = None if "name" in _doc: try: name = load_field( _doc.get("name"), uri_union_of_None_type_or_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("name") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `name`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("name") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [e], detailed_message=f"the `name` field with value `{val}` " "is not valid because:", ) ) __original_name_is_none = name is None if name is None: if docRoot is not None: name = docRoot else: name = "_:" + str(_uuid__.uuid4()) if not __original_name_is_none: baseuri = cast(str, name) try: if _doc.get("symbols") is None: raise ValidationException("missing required field `symbols`", None, []) symbols = load_field( _doc.get("symbols"), uri_array_of_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("symbols") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `symbols`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("symbols") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `symbols` field is not valid because:", SourceLine(_doc, "symbols", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `symbols` field is not valid because:", SourceLine(_doc, "symbols", str), [e], detailed_message=f"the `symbols` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("type") is None: raise ValidationException("missing required field `type`", None, []) type_ = load_field( _doc.get("type"), typedsl_Enum_nameLoader_2, baseuri, loadingOptions, lc=_doc.get("type") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `type`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("type") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [e], detailed_message=f"the `type` field with value `{val}` " "is not valid because:", ) ) label = None if "label" in _doc: try: label = load_field( _doc.get("label"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("label") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `label`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("label") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [e], detailed_message=f"the `label` field with value `{val}` " "is not valid because:", ) ) doc = None if "doc" in _doc: try: doc = load_field( _doc.get("doc"), union_of_None_type_or_strtype_or_array_of_strtype, baseuri, loadingOptions, lc=_doc.get("doc") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `doc`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("doc") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [e], detailed_message=f"the `doc` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `name`, `symbols`, `type`, `label`, `doc`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( name=name, symbols=symbols, type_=type_, label=label, doc=doc, extension_fields=extension_fields, loadingOptions=loadingOptions, ) loadingOptions.idx[cast(str, name)] = (_constructed, loadingOptions) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.name is not None: u = save_relative_uri(self.name, base_url, True, None, relative_uris) r["name"] = u if self.symbols is not None: u = save_relative_uri(self.symbols, self.name, True, None, relative_uris) r["symbols"] = u if self.type_ is not None: r["type"] = save( self.type_, top=False, base_url=self.name, relative_uris=relative_uris ) if self.label is not None: r["label"] = save( self.label, top=False, base_url=self.name, relative_uris=relative_uris ) if self.doc is not None: r["doc"] = save( self.doc, top=False, base_url=self.name, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["name", "symbols", "type", "label", "doc"]) class OutputArraySchema(CWLArraySchema, OutputSchema): name: str def __init__( self, items: Any, type_: Any, label: Optional[Any] = None, doc: Optional[Any] = None, name: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.items = items self.type_ = type_ self.label = label self.doc = doc self.name = name if name is not None else "_:" + str(_uuid__.uuid4()) def __eq__(self, other: Any) -> bool: if isinstance(other, OutputArraySchema): return bool( self.items == other.items and self.type_ == other.type_ and self.label == other.label and self.doc == other.doc and self.name == other.name ) return False def __hash__(self) -> int: return hash((self.items, self.type_, self.label, self.doc, self.name)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "OutputArraySchema": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] name = None if "name" in _doc: try: name = load_field( _doc.get("name"), uri_union_of_None_type_or_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("name") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `name`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("name") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [e], detailed_message=f"the `name` field with value `{val}` " "is not valid because:", ) ) __original_name_is_none = name is None if name is None: if docRoot is not None: name = docRoot else: name = "_:" + str(_uuid__.uuid4()) if not __original_name_is_none: baseuri = cast(str, name) try: if _doc.get("items") is None: raise ValidationException("missing required field `items`", None, []) items = load_field( _doc.get("items"), uri_union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype_False_True_2_None, baseuri, loadingOptions, lc=_doc.get("items") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `items`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("items") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `items` field is not valid because:", SourceLine(_doc, "items", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `items` field is not valid because:", SourceLine(_doc, "items", str), [e], detailed_message=f"the `items` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("type") is None: raise ValidationException("missing required field `type`", None, []) type_ = load_field( _doc.get("type"), typedsl_Array_nameLoader_2, baseuri, loadingOptions, lc=_doc.get("type") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `type`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("type") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [e], detailed_message=f"the `type` field with value `{val}` " "is not valid because:", ) ) label = None if "label" in _doc: try: label = load_field( _doc.get("label"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("label") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `label`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("label") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [e], detailed_message=f"the `label` field with value `{val}` " "is not valid because:", ) ) doc = None if "doc" in _doc: try: doc = load_field( _doc.get("doc"), union_of_None_type_or_strtype_or_array_of_strtype, baseuri, loadingOptions, lc=_doc.get("doc") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `doc`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("doc") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [e], detailed_message=f"the `doc` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `items`, `type`, `label`, `doc`, `name`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( items=items, type_=type_, label=label, doc=doc, name=name, extension_fields=extension_fields, loadingOptions=loadingOptions, ) loadingOptions.idx[cast(str, name)] = (_constructed, loadingOptions) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.name is not None: u = save_relative_uri(self.name, base_url, True, None, relative_uris) r["name"] = u if self.items is not None: u = save_relative_uri(self.items, self.name, False, 2, relative_uris) r["items"] = u if self.type_ is not None: r["type"] = save( self.type_, top=False, base_url=self.name, relative_uris=relative_uris ) if self.label is not None: r["label"] = save( self.label, top=False, base_url=self.name, relative_uris=relative_uris ) if self.doc is not None: r["doc"] = save( self.doc, top=False, base_url=self.name, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["items", "type", "label", "doc", "name"]) class InputParameter(Parameter, InputFormat, LoadContents): pass class OutputParameter(Parameter, OutputFormat): pass class ProcessRequirement(Saveable): """ A process requirement declares a prerequisite that may or must be fulfilled before executing a process. See [`Process.hints`](#process) and [`Process.requirements`](#process). Process requirements are the primary mechanism for specifying extensions to the CWL core specification. """ pass class Process(Identified, Labeled, Documented): """ The base executable type in CWL is the `Process` object defined by the document. Note that the `Process` object is abstract and cannot be directly executed. """ pass class InlineJavascriptRequirement(ProcessRequirement): """ Indicates that the workflow platform must support inline Javascript expressions. If this requirement is not present, the workflow platform must not perform expression interpolation. """ def __init__( self, expressionLib: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.class_ = "InlineJavascriptRequirement" self.expressionLib = expressionLib def __eq__(self, other: Any) -> bool: if isinstance(other, InlineJavascriptRequirement): return bool( self.class_ == other.class_ and self.expressionLib == other.expressionLib ) return False def __hash__(self) -> int: return hash((self.class_, self.expressionLib)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "InlineJavascriptRequirement": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("class") is None: raise ValidationException("missing required field `class`", None, []) class_ = load_field( _doc.get("class"), uri_InlineJavascriptRequirement_classLoader_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("class") ) if class_ not in (cls.__name__, loadingOptions.vocab.get(cls.__name__)): raise ValidationException(f"tried `{cls.__name__}` but") except ValidationException as e: raise e expressionLib = None if "expressionLib" in _doc: try: expressionLib = load_field( _doc.get("expressionLib"), union_of_None_type_or_array_of_strtype, baseuri, loadingOptions, lc=_doc.get("expressionLib") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `expressionLib`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("expressionLib") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `expressionLib` field is not valid because:", SourceLine(_doc, "expressionLib", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `expressionLib` field is not valid because:", SourceLine(_doc, "expressionLib", str), [e], detailed_message=f"the `expressionLib` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `class`, `expressionLib`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( expressionLib=expressionLib, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.class_ is not None: uri = self.loadingOptions.vocab[self.class_] if p := self.loadingOptions.rvocab.get(uri[: -len(self.class_)]): uri = f"{p}:{self.class_}" else: uri = self.class_ u = save_relative_uri(uri, base_url, False, None, relative_uris) r["class"] = u if self.expressionLib is not None: r["expressionLib"] = save( self.expressionLib, top=False, base_url=base_url, relative_uris=relative_uris, ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["class", "expressionLib"]) class CommandInputSchema(Saveable): pass class SchemaDefRequirement(ProcessRequirement): """ This field consists of an array of type definitions which must be used when interpreting the `inputs` and `outputs` fields. When a `type` field contains a IRI, the implementation must check if the type is defined in `schemaDefs` and use that definition. If the type is not found in `schemaDefs`, it is an error. The entries in `schemaDefs` must be processed in the order listed such that later schema definitions may refer to earlier schema definitions. - **Type definitions are allowed for `enum` and `record` types only.** - Type definitions may be shared by defining them in a file and then `$include`-ing them in the `types` field. - A file can contain a list of type definitions """ def __init__( self, types: Any, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.class_ = "SchemaDefRequirement" self.types = types def __eq__(self, other: Any) -> bool: if isinstance(other, SchemaDefRequirement): return bool(self.class_ == other.class_ and self.types == other.types) return False def __hash__(self) -> int: return hash((self.class_, self.types)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "SchemaDefRequirement": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("class") is None: raise ValidationException("missing required field `class`", None, []) class_ = load_field( _doc.get("class"), uri_SchemaDefRequirement_classLoader_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("class") ) if class_ not in (cls.__name__, loadingOptions.vocab.get(cls.__name__)): raise ValidationException(f"tried `{cls.__name__}` but") except ValidationException as e: raise e try: if _doc.get("types") is None: raise ValidationException("missing required field `types`", None, []) types = load_field( _doc.get("types"), array_of_union_of_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader, baseuri, loadingOptions, lc=_doc.get("types") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `types`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("types") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `types` field is not valid because:", SourceLine(_doc, "types", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `types` field is not valid because:", SourceLine(_doc, "types", str), [e], detailed_message=f"the `types` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `class`, `types`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( types=types, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.class_ is not None: uri = self.loadingOptions.vocab[self.class_] if p := self.loadingOptions.rvocab.get(uri[: -len(self.class_)]): uri = f"{p}:{self.class_}" else: uri = self.class_ u = save_relative_uri(uri, base_url, False, None, relative_uris) r["class"] = u if self.types is not None: r["types"] = save( self.types, top=False, base_url=base_url, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["class", "types"]) class SecondaryFileSchema(Saveable): """ Secondary files are specified using the following micro-DSL for secondary files: * If the value is a string, it is transformed to an object with two fields `pattern` and `required` * By default, the value of `required` is `null` (this indicates default behavior, which may be based on the context) * If the value ends with a question mark `?` the question mark is stripped off and the value of the field `required` is set to `False` * The remaining value is assigned to the field `pattern` For implementation details and examples, please see [this section](SchemaSalad.html#Domain_Specific_Language_for_secondary_files) in the Schema Salad specification. """ def __init__( self, pattern: Any, required: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.pattern = pattern self.required = required def __eq__(self, other: Any) -> bool: if isinstance(other, SecondaryFileSchema): return bool( self.pattern == other.pattern and self.required == other.required ) return False def __hash__(self) -> int: return hash((self.pattern, self.required)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "SecondaryFileSchema": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("pattern") is None: raise ValidationException("missing required field `pattern`", None, []) pattern = load_field( _doc.get("pattern"), union_of_strtype_or_ExpressionLoader, baseuri, loadingOptions, lc=_doc.get("pattern") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `pattern`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("pattern") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `pattern` field is not valid because:", SourceLine(_doc, "pattern", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `pattern` field is not valid because:", SourceLine(_doc, "pattern", str), [e], detailed_message=f"the `pattern` field with value `{val}` " "is not valid because:", ) ) required = None if "required" in _doc: try: required = load_field( _doc.get("required"), union_of_None_type_or_booltype_or_ExpressionLoader, baseuri, loadingOptions, lc=_doc.get("required") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `required`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("required") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `required` field is not valid because:", SourceLine(_doc, "required", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `required` field is not valid because:", SourceLine(_doc, "required", str), [e], detailed_message=f"the `required` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `pattern`, `required`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( pattern=pattern, required=required, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.pattern is not None: r["pattern"] = save( self.pattern, top=False, base_url=base_url, relative_uris=relative_uris ) if self.required is not None: r["required"] = save( self.required, top=False, base_url=base_url, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["pattern", "required"]) class LoadListingRequirement(ProcessRequirement): """ Specify the desired behavior for loading the `listing` field of a Directory object for use by expressions. """ def __init__( self, loadListing: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.class_ = "LoadListingRequirement" self.loadListing = loadListing def __eq__(self, other: Any) -> bool: if isinstance(other, LoadListingRequirement): return bool( self.class_ == other.class_ and self.loadListing == other.loadListing ) return False def __hash__(self) -> int: return hash((self.class_, self.loadListing)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "LoadListingRequirement": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("class") is None: raise ValidationException("missing required field `class`", None, []) class_ = load_field( _doc.get("class"), uri_LoadListingRequirement_classLoader_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("class") ) if class_ not in (cls.__name__, loadingOptions.vocab.get(cls.__name__)): raise ValidationException(f"tried `{cls.__name__}` but") except ValidationException as e: raise e loadListing = None if "loadListing" in _doc: try: loadListing = load_field( _doc.get("loadListing"), union_of_None_type_or_LoadListingEnumLoader, baseuri, loadingOptions, lc=_doc.get("loadListing") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `loadListing`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("loadListing") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `loadListing` field is not valid because:", SourceLine(_doc, "loadListing", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `loadListing` field is not valid because:", SourceLine(_doc, "loadListing", str), [e], detailed_message=f"the `loadListing` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `class`, `loadListing`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( loadListing=loadListing, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.class_ is not None: uri = self.loadingOptions.vocab[self.class_] if p := self.loadingOptions.rvocab.get(uri[: -len(self.class_)]): uri = f"{p}:{self.class_}" else: uri = self.class_ u = save_relative_uri(uri, base_url, False, None, relative_uris) r["class"] = u if self.loadListing is not None: r["loadListing"] = save( self.loadListing, top=False, base_url=base_url, relative_uris=relative_uris, ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["class", "loadListing"]) class EnvironmentDef(Saveable): """ Define an environment variable that will be set in the runtime environment by the workflow platform when executing the command line tool. May be the result of executing an expression, such as getting a parameter from input. """ def __init__( self, envName: Any, envValue: Any, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.envName = envName self.envValue = envValue def __eq__(self, other: Any) -> bool: if isinstance(other, EnvironmentDef): return bool( self.envName == other.envName and self.envValue == other.envValue ) return False def __hash__(self) -> int: return hash((self.envName, self.envValue)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "EnvironmentDef": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("envName") is None: raise ValidationException("missing required field `envName`", None, []) envName = load_field( _doc.get("envName"), strtype, baseuri, loadingOptions, lc=_doc.get("envName") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `envName`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("envName") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `envName` field is not valid because:", SourceLine(_doc, "envName", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `envName` field is not valid because:", SourceLine(_doc, "envName", str), [e], detailed_message=f"the `envName` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("envValue") is None: raise ValidationException("missing required field `envValue`", None, []) envValue = load_field( _doc.get("envValue"), union_of_strtype_or_ExpressionLoader, baseuri, loadingOptions, lc=_doc.get("envValue") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `envValue`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("envValue") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `envValue` field is not valid because:", SourceLine(_doc, "envValue", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `envValue` field is not valid because:", SourceLine(_doc, "envValue", str), [e], detailed_message=f"the `envValue` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `envName`, `envValue`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( envName=envName, envValue=envValue, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.envName is not None: r["envName"] = save( self.envName, top=False, base_url=base_url, relative_uris=relative_uris ) if self.envValue is not None: r["envValue"] = save( self.envValue, top=False, base_url=base_url, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["envName", "envValue"]) class CommandLineBinding(InputBinding): """ When listed under `inputBinding` in the input schema, the term "value" refers to the corresponding value in the input object. For binding objects listed in `CommandLineTool.arguments`, the term "value" refers to the effective value after evaluating `valueFrom`. The binding behavior when building the command line depends on the data type of the value. If there is a mismatch between the type described by the input schema and the effective value, such as resulting from an expression evaluation, an implementation must use the data type of the effective value. - **string**: Add `prefix` and the string to the command line. - **number**: Add `prefix` and decimal representation to command line. - **boolean**: If true, add `prefix` to the command line. If false, add nothing. - **File**: Add `prefix` and the value of [`File.path`](#File) to the command line. - **Directory**: Add `prefix` and the value of [`Directory.path`](#Directory) to the command line. - **array**: If `itemSeparator` is specified, add `prefix` and the join the array into a single string with `itemSeparator` separating the items. Otherwise, first add `prefix`, then recursively process individual elements. If the array is empty, it does not add anything to command line. - **object**: Add `prefix` only, and recursively add object fields for which `inputBinding` is specified. - **null**: Add nothing. """ def __init__( self, loadContents: Optional[Any] = None, position: Optional[Any] = None, prefix: Optional[Any] = None, separate: Optional[Any] = None, itemSeparator: Optional[Any] = None, valueFrom: Optional[Any] = None, shellQuote: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.loadContents = loadContents self.position = position self.prefix = prefix self.separate = separate self.itemSeparator = itemSeparator self.valueFrom = valueFrom self.shellQuote = shellQuote def __eq__(self, other: Any) -> bool: if isinstance(other, CommandLineBinding): return bool( self.loadContents == other.loadContents and self.position == other.position and self.prefix == other.prefix and self.separate == other.separate and self.itemSeparator == other.itemSeparator and self.valueFrom == other.valueFrom and self.shellQuote == other.shellQuote ) return False def __hash__(self) -> int: return hash( ( self.loadContents, self.position, self.prefix, self.separate, self.itemSeparator, self.valueFrom, self.shellQuote, ) ) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "CommandLineBinding": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] loadContents = None if "loadContents" in _doc: try: loadContents = load_field( _doc.get("loadContents"), union_of_None_type_or_booltype, baseuri, loadingOptions, lc=_doc.get("loadContents") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `loadContents`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("loadContents") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `loadContents` field is not valid because:", SourceLine(_doc, "loadContents", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `loadContents` field is not valid because:", SourceLine(_doc, "loadContents", str), [e], detailed_message=f"the `loadContents` field with value `{val}` " "is not valid because:", ) ) position = None if "position" in _doc: try: position = load_field( _doc.get("position"), union_of_None_type_or_inttype_or_ExpressionLoader, baseuri, loadingOptions, lc=_doc.get("position") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `position`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("position") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `position` field is not valid because:", SourceLine(_doc, "position", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `position` field is not valid because:", SourceLine(_doc, "position", str), [e], detailed_message=f"the `position` field with value `{val}` " "is not valid because:", ) ) prefix = None if "prefix" in _doc: try: prefix = load_field( _doc.get("prefix"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("prefix") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `prefix`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("prefix") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `prefix` field is not valid because:", SourceLine(_doc, "prefix", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `prefix` field is not valid because:", SourceLine(_doc, "prefix", str), [e], detailed_message=f"the `prefix` field with value `{val}` " "is not valid because:", ) ) separate = None if "separate" in _doc: try: separate = load_field( _doc.get("separate"), union_of_None_type_or_booltype, baseuri, loadingOptions, lc=_doc.get("separate") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `separate`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("separate") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `separate` field is not valid because:", SourceLine(_doc, "separate", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `separate` field is not valid because:", SourceLine(_doc, "separate", str), [e], detailed_message=f"the `separate` field with value `{val}` " "is not valid because:", ) ) itemSeparator = None if "itemSeparator" in _doc: try: itemSeparator = load_field( _doc.get("itemSeparator"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("itemSeparator") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `itemSeparator`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("itemSeparator") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `itemSeparator` field is not valid because:", SourceLine(_doc, "itemSeparator", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `itemSeparator` field is not valid because:", SourceLine(_doc, "itemSeparator", str), [e], detailed_message=f"the `itemSeparator` field with value `{val}` " "is not valid because:", ) ) valueFrom = None if "valueFrom" in _doc: try: valueFrom = load_field( _doc.get("valueFrom"), union_of_None_type_or_strtype_or_ExpressionLoader, baseuri, loadingOptions, lc=_doc.get("valueFrom") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `valueFrom`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("valueFrom") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `valueFrom` field is not valid because:", SourceLine(_doc, "valueFrom", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `valueFrom` field is not valid because:", SourceLine(_doc, "valueFrom", str), [e], detailed_message=f"the `valueFrom` field with value `{val}` " "is not valid because:", ) ) shellQuote = None if "shellQuote" in _doc: try: shellQuote = load_field( _doc.get("shellQuote"), union_of_None_type_or_booltype, baseuri, loadingOptions, lc=_doc.get("shellQuote") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `shellQuote`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("shellQuote") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `shellQuote` field is not valid because:", SourceLine(_doc, "shellQuote", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `shellQuote` field is not valid because:", SourceLine(_doc, "shellQuote", str), [e], detailed_message=f"the `shellQuote` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `loadContents`, `position`, `prefix`, `separate`, `itemSeparator`, `valueFrom`, `shellQuote`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( loadContents=loadContents, position=position, prefix=prefix, separate=separate, itemSeparator=itemSeparator, valueFrom=valueFrom, shellQuote=shellQuote, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.loadContents is not None: r["loadContents"] = save( self.loadContents, top=False, base_url=base_url, relative_uris=relative_uris, ) if self.position is not None: r["position"] = save( self.position, top=False, base_url=base_url, relative_uris=relative_uris ) if self.prefix is not None: r["prefix"] = save( self.prefix, top=False, base_url=base_url, relative_uris=relative_uris ) if self.separate is not None: r["separate"] = save( self.separate, top=False, base_url=base_url, relative_uris=relative_uris ) if self.itemSeparator is not None: r["itemSeparator"] = save( self.itemSeparator, top=False, base_url=base_url, relative_uris=relative_uris, ) if self.valueFrom is not None: r["valueFrom"] = save( self.valueFrom, top=False, base_url=base_url, relative_uris=relative_uris, ) if self.shellQuote is not None: r["shellQuote"] = save( self.shellQuote, top=False, base_url=base_url, relative_uris=relative_uris, ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset( [ "loadContents", "position", "prefix", "separate", "itemSeparator", "valueFrom", "shellQuote", ] ) class CommandOutputBinding(LoadContents): """ Describes how to generate an output parameter based on the files produced by a CommandLineTool. The output parameter value is generated by applying these operations in the following order: - glob - loadContents - outputEval - secondaryFiles """ def __init__( self, loadContents: Optional[Any] = None, loadListing: Optional[Any] = None, glob: Optional[Any] = None, outputEval: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.loadContents = loadContents self.loadListing = loadListing self.glob = glob self.outputEval = outputEval def __eq__(self, other: Any) -> bool: if isinstance(other, CommandOutputBinding): return bool( self.loadContents == other.loadContents and self.loadListing == other.loadListing and self.glob == other.glob and self.outputEval == other.outputEval ) return False def __hash__(self) -> int: return hash((self.loadContents, self.loadListing, self.glob, self.outputEval)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "CommandOutputBinding": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] loadContents = None if "loadContents" in _doc: try: loadContents = load_field( _doc.get("loadContents"), union_of_None_type_or_booltype, baseuri, loadingOptions, lc=_doc.get("loadContents") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `loadContents`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("loadContents") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `loadContents` field is not valid because:", SourceLine(_doc, "loadContents", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `loadContents` field is not valid because:", SourceLine(_doc, "loadContents", str), [e], detailed_message=f"the `loadContents` field with value `{val}` " "is not valid because:", ) ) loadListing = None if "loadListing" in _doc: try: loadListing = load_field( _doc.get("loadListing"), union_of_None_type_or_LoadListingEnumLoader, baseuri, loadingOptions, lc=_doc.get("loadListing") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `loadListing`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("loadListing") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `loadListing` field is not valid because:", SourceLine(_doc, "loadListing", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `loadListing` field is not valid because:", SourceLine(_doc, "loadListing", str), [e], detailed_message=f"the `loadListing` field with value `{val}` " "is not valid because:", ) ) glob = None if "glob" in _doc: try: glob = load_field( _doc.get("glob"), union_of_None_type_or_strtype_or_ExpressionLoader_or_array_of_strtype, baseuri, loadingOptions, lc=_doc.get("glob") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `glob`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("glob") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `glob` field is not valid because:", SourceLine(_doc, "glob", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `glob` field is not valid because:", SourceLine(_doc, "glob", str), [e], detailed_message=f"the `glob` field with value `{val}` " "is not valid because:", ) ) outputEval = None if "outputEval" in _doc: try: outputEval = load_field( _doc.get("outputEval"), union_of_None_type_or_ExpressionLoader, baseuri, loadingOptions, lc=_doc.get("outputEval") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `outputEval`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("outputEval") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `outputEval` field is not valid because:", SourceLine(_doc, "outputEval", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `outputEval` field is not valid because:", SourceLine(_doc, "outputEval", str), [e], detailed_message=f"the `outputEval` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `loadContents`, `loadListing`, `glob`, `outputEval`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( loadContents=loadContents, loadListing=loadListing, glob=glob, outputEval=outputEval, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.loadContents is not None: r["loadContents"] = save( self.loadContents, top=False, base_url=base_url, relative_uris=relative_uris, ) if self.loadListing is not None: r["loadListing"] = save( self.loadListing, top=False, base_url=base_url, relative_uris=relative_uris, ) if self.glob is not None: r["glob"] = save( self.glob, top=False, base_url=base_url, relative_uris=relative_uris ) if self.outputEval is not None: r["outputEval"] = save( self.outputEval, top=False, base_url=base_url, relative_uris=relative_uris, ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["loadContents", "loadListing", "glob", "outputEval"]) class CommandLineBindable(Saveable): pass class CommandInputRecordField(InputRecordField, CommandLineBindable): name: str def __init__( self, name: Any, type_: Any, doc: Optional[Any] = None, label: Optional[Any] = None, secondaryFiles: Optional[Any] = None, streamable: Optional[Any] = None, format: Optional[Any] = None, loadContents: Optional[Any] = None, loadListing: Optional[Any] = None, inputBinding: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.doc = doc self.name = name if name is not None else "_:" + str(_uuid__.uuid4()) self.type_ = type_ self.label = label self.secondaryFiles = secondaryFiles self.streamable = streamable self.format = format self.loadContents = loadContents self.loadListing = loadListing self.inputBinding = inputBinding def __eq__(self, other: Any) -> bool: if isinstance(other, CommandInputRecordField): return bool( self.doc == other.doc and self.name == other.name and self.type_ == other.type_ and self.label == other.label and self.secondaryFiles == other.secondaryFiles and self.streamable == other.streamable and self.format == other.format and self.loadContents == other.loadContents and self.loadListing == other.loadListing and self.inputBinding == other.inputBinding ) return False def __hash__(self) -> int: return hash( ( self.doc, self.name, self.type_, self.label, self.secondaryFiles, self.streamable, self.format, self.loadContents, self.loadListing, self.inputBinding, ) ) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "CommandInputRecordField": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] name = None if "name" in _doc: try: name = load_field( _doc.get("name"), uri_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("name") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `name`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("name") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [e], detailed_message=f"the `name` field with value `{val}` " "is not valid because:", ) ) __original_name_is_none = name is None if name is None: if docRoot is not None: name = docRoot else: _errors__.append(ValidationException("missing name")) if not __original_name_is_none: baseuri = cast(str, name) doc = None if "doc" in _doc: try: doc = load_field( _doc.get("doc"), union_of_None_type_or_strtype_or_array_of_strtype, baseuri, loadingOptions, lc=_doc.get("doc") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `doc`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("doc") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [e], detailed_message=f"the `doc` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("type") is None: raise ValidationException("missing required field `type`", None, []) type_ = load_field( _doc.get("type"), typedsl_union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype_2, baseuri, loadingOptions, lc=_doc.get("type") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `type`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("type") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [e], detailed_message=f"the `type` field with value `{val}` " "is not valid because:", ) ) label = None if "label" in _doc: try: label = load_field( _doc.get("label"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("label") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `label`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("label") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [e], detailed_message=f"the `label` field with value `{val}` " "is not valid because:", ) ) secondaryFiles = None if "secondaryFiles" in _doc: try: secondaryFiles = load_field( _doc.get("secondaryFiles"), secondaryfilesdsl_union_of_None_type_or_SecondaryFileSchemaLoader_or_array_of_SecondaryFileSchemaLoader, baseuri, loadingOptions, lc=_doc.get("secondaryFiles") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `secondaryFiles`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("secondaryFiles") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `secondaryFiles` field is not valid because:", SourceLine(_doc, "secondaryFiles", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `secondaryFiles` field is not valid because:", SourceLine(_doc, "secondaryFiles", str), [e], detailed_message=f"the `secondaryFiles` field with value `{val}` " "is not valid because:", ) ) streamable = None if "streamable" in _doc: try: streamable = load_field( _doc.get("streamable"), union_of_None_type_or_booltype, baseuri, loadingOptions, lc=_doc.get("streamable") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `streamable`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("streamable") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `streamable` field is not valid because:", SourceLine(_doc, "streamable", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `streamable` field is not valid because:", SourceLine(_doc, "streamable", str), [e], detailed_message=f"the `streamable` field with value `{val}` " "is not valid because:", ) ) format = None if "format" in _doc: try: format = load_field( _doc.get("format"), uri_union_of_None_type_or_strtype_or_array_of_strtype_or_ExpressionLoader_True_False_None_True, baseuri, loadingOptions, lc=_doc.get("format") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `format`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("format") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `format` field is not valid because:", SourceLine(_doc, "format", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `format` field is not valid because:", SourceLine(_doc, "format", str), [e], detailed_message=f"the `format` field with value `{val}` " "is not valid because:", ) ) loadContents = None if "loadContents" in _doc: try: loadContents = load_field( _doc.get("loadContents"), union_of_None_type_or_booltype, baseuri, loadingOptions, lc=_doc.get("loadContents") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `loadContents`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("loadContents") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `loadContents` field is not valid because:", SourceLine(_doc, "loadContents", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `loadContents` field is not valid because:", SourceLine(_doc, "loadContents", str), [e], detailed_message=f"the `loadContents` field with value `{val}` " "is not valid because:", ) ) loadListing = None if "loadListing" in _doc: try: loadListing = load_field( _doc.get("loadListing"), union_of_None_type_or_LoadListingEnumLoader, baseuri, loadingOptions, lc=_doc.get("loadListing") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `loadListing`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("loadListing") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `loadListing` field is not valid because:", SourceLine(_doc, "loadListing", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `loadListing` field is not valid because:", SourceLine(_doc, "loadListing", str), [e], detailed_message=f"the `loadListing` field with value `{val}` " "is not valid because:", ) ) inputBinding = None if "inputBinding" in _doc: try: inputBinding = load_field( _doc.get("inputBinding"), union_of_None_type_or_CommandLineBindingLoader, baseuri, loadingOptions, lc=_doc.get("inputBinding") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `inputBinding`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("inputBinding") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `inputBinding` field is not valid because:", SourceLine(_doc, "inputBinding", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `inputBinding` field is not valid because:", SourceLine(_doc, "inputBinding", str), [e], detailed_message=f"the `inputBinding` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `doc`, `name`, `type`, `label`, `secondaryFiles`, `streamable`, `format`, `loadContents`, `loadListing`, `inputBinding`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( doc=doc, name=name, type_=type_, label=label, secondaryFiles=secondaryFiles, streamable=streamable, format=format, loadContents=loadContents, loadListing=loadListing, inputBinding=inputBinding, extension_fields=extension_fields, loadingOptions=loadingOptions, ) loadingOptions.idx[cast(str, name)] = (_constructed, loadingOptions) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.name is not None: u = save_relative_uri(self.name, base_url, True, None, relative_uris) r["name"] = u if self.doc is not None: r["doc"] = save( self.doc, top=False, base_url=self.name, relative_uris=relative_uris ) if self.type_ is not None: r["type"] = save( self.type_, top=False, base_url=self.name, relative_uris=relative_uris ) if self.label is not None: r["label"] = save( self.label, top=False, base_url=self.name, relative_uris=relative_uris ) if self.secondaryFiles is not None: r["secondaryFiles"] = save( self.secondaryFiles, top=False, base_url=self.name, relative_uris=relative_uris, ) if self.streamable is not None: r["streamable"] = save( self.streamable, top=False, base_url=self.name, relative_uris=relative_uris, ) if self.format is not None: u = save_relative_uri(self.format, self.name, True, None, relative_uris) r["format"] = u if self.loadContents is not None: r["loadContents"] = save( self.loadContents, top=False, base_url=self.name, relative_uris=relative_uris, ) if self.loadListing is not None: r["loadListing"] = save( self.loadListing, top=False, base_url=self.name, relative_uris=relative_uris, ) if self.inputBinding is not None: r["inputBinding"] = save( self.inputBinding, top=False, base_url=self.name, relative_uris=relative_uris, ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset( [ "doc", "name", "type", "label", "secondaryFiles", "streamable", "format", "loadContents", "loadListing", "inputBinding", ] ) class CommandInputRecordSchema( InputRecordSchema, CommandInputSchema, CommandLineBindable ): name: str def __init__( self, type_: Any, fields: Optional[Any] = None, label: Optional[Any] = None, doc: Optional[Any] = None, name: Optional[Any] = None, inputBinding: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.fields = fields self.type_ = type_ self.label = label self.doc = doc self.name = name if name is not None else "_:" + str(_uuid__.uuid4()) self.inputBinding = inputBinding def __eq__(self, other: Any) -> bool: if isinstance(other, CommandInputRecordSchema): return bool( self.fields == other.fields and self.type_ == other.type_ and self.label == other.label and self.doc == other.doc and self.name == other.name and self.inputBinding == other.inputBinding ) return False def __hash__(self) -> int: return hash( ( self.fields, self.type_, self.label, self.doc, self.name, self.inputBinding, ) ) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "CommandInputRecordSchema": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] name = None if "name" in _doc: try: name = load_field( _doc.get("name"), uri_union_of_None_type_or_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("name") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `name`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("name") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [e], detailed_message=f"the `name` field with value `{val}` " "is not valid because:", ) ) __original_name_is_none = name is None if name is None: if docRoot is not None: name = docRoot else: name = "_:" + str(_uuid__.uuid4()) if not __original_name_is_none: baseuri = cast(str, name) fields = None if "fields" in _doc: try: fields = load_field( _doc.get("fields"), idmap_fields_union_of_None_type_or_array_of_CommandInputRecordFieldLoader, baseuri, loadingOptions, lc=_doc.get("fields") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `fields`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("fields") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `fields` field is not valid because:", SourceLine(_doc, "fields", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `fields` field is not valid because:", SourceLine(_doc, "fields", str), [e], detailed_message=f"the `fields` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("type") is None: raise ValidationException("missing required field `type`", None, []) type_ = load_field( _doc.get("type"), typedsl_Record_nameLoader_2, baseuri, loadingOptions, lc=_doc.get("type") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `type`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("type") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [e], detailed_message=f"the `type` field with value `{val}` " "is not valid because:", ) ) label = None if "label" in _doc: try: label = load_field( _doc.get("label"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("label") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `label`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("label") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [e], detailed_message=f"the `label` field with value `{val}` " "is not valid because:", ) ) doc = None if "doc" in _doc: try: doc = load_field( _doc.get("doc"), union_of_None_type_or_strtype_or_array_of_strtype, baseuri, loadingOptions, lc=_doc.get("doc") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `doc`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("doc") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [e], detailed_message=f"the `doc` field with value `{val}` " "is not valid because:", ) ) inputBinding = None if "inputBinding" in _doc: try: inputBinding = load_field( _doc.get("inputBinding"), union_of_None_type_or_CommandLineBindingLoader, baseuri, loadingOptions, lc=_doc.get("inputBinding") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `inputBinding`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("inputBinding") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `inputBinding` field is not valid because:", SourceLine(_doc, "inputBinding", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `inputBinding` field is not valid because:", SourceLine(_doc, "inputBinding", str), [e], detailed_message=f"the `inputBinding` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `fields`, `type`, `label`, `doc`, `name`, `inputBinding`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( fields=fields, type_=type_, label=label, doc=doc, name=name, inputBinding=inputBinding, extension_fields=extension_fields, loadingOptions=loadingOptions, ) loadingOptions.idx[cast(str, name)] = (_constructed, loadingOptions) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.name is not None: u = save_relative_uri(self.name, base_url, True, None, relative_uris) r["name"] = u if self.fields is not None: r["fields"] = save( self.fields, top=False, base_url=self.name, relative_uris=relative_uris ) if self.type_ is not None: r["type"] = save( self.type_, top=False, base_url=self.name, relative_uris=relative_uris ) if self.label is not None: r["label"] = save( self.label, top=False, base_url=self.name, relative_uris=relative_uris ) if self.doc is not None: r["doc"] = save( self.doc, top=False, base_url=self.name, relative_uris=relative_uris ) if self.inputBinding is not None: r["inputBinding"] = save( self.inputBinding, top=False, base_url=self.name, relative_uris=relative_uris, ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["fields", "type", "label", "doc", "name", "inputBinding"]) class CommandInputEnumSchema(InputEnumSchema, CommandInputSchema, CommandLineBindable): name: str def __init__( self, symbols: Any, type_: Any, name: Optional[Any] = None, label: Optional[Any] = None, doc: Optional[Any] = None, inputBinding: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.name = name if name is not None else "_:" + str(_uuid__.uuid4()) self.symbols = symbols self.type_ = type_ self.label = label self.doc = doc self.inputBinding = inputBinding def __eq__(self, other: Any) -> bool: if isinstance(other, CommandInputEnumSchema): return bool( self.name == other.name and self.symbols == other.symbols and self.type_ == other.type_ and self.label == other.label and self.doc == other.doc and self.inputBinding == other.inputBinding ) return False def __hash__(self) -> int: return hash( ( self.name, self.symbols, self.type_, self.label, self.doc, self.inputBinding, ) ) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "CommandInputEnumSchema": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] name = None if "name" in _doc: try: name = load_field( _doc.get("name"), uri_union_of_None_type_or_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("name") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `name`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("name") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [e], detailed_message=f"the `name` field with value `{val}` " "is not valid because:", ) ) __original_name_is_none = name is None if name is None: if docRoot is not None: name = docRoot else: name = "_:" + str(_uuid__.uuid4()) if not __original_name_is_none: baseuri = cast(str, name) try: if _doc.get("symbols") is None: raise ValidationException("missing required field `symbols`", None, []) symbols = load_field( _doc.get("symbols"), uri_array_of_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("symbols") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `symbols`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("symbols") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `symbols` field is not valid because:", SourceLine(_doc, "symbols", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `symbols` field is not valid because:", SourceLine(_doc, "symbols", str), [e], detailed_message=f"the `symbols` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("type") is None: raise ValidationException("missing required field `type`", None, []) type_ = load_field( _doc.get("type"), typedsl_Enum_nameLoader_2, baseuri, loadingOptions, lc=_doc.get("type") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `type`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("type") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [e], detailed_message=f"the `type` field with value `{val}` " "is not valid because:", ) ) label = None if "label" in _doc: try: label = load_field( _doc.get("label"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("label") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `label`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("label") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [e], detailed_message=f"the `label` field with value `{val}` " "is not valid because:", ) ) doc = None if "doc" in _doc: try: doc = load_field( _doc.get("doc"), union_of_None_type_or_strtype_or_array_of_strtype, baseuri, loadingOptions, lc=_doc.get("doc") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `doc`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("doc") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [e], detailed_message=f"the `doc` field with value `{val}` " "is not valid because:", ) ) inputBinding = None if "inputBinding" in _doc: try: inputBinding = load_field( _doc.get("inputBinding"), union_of_None_type_or_CommandLineBindingLoader, baseuri, loadingOptions, lc=_doc.get("inputBinding") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `inputBinding`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("inputBinding") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `inputBinding` field is not valid because:", SourceLine(_doc, "inputBinding", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `inputBinding` field is not valid because:", SourceLine(_doc, "inputBinding", str), [e], detailed_message=f"the `inputBinding` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `name`, `symbols`, `type`, `label`, `doc`, `inputBinding`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( name=name, symbols=symbols, type_=type_, label=label, doc=doc, inputBinding=inputBinding, extension_fields=extension_fields, loadingOptions=loadingOptions, ) loadingOptions.idx[cast(str, name)] = (_constructed, loadingOptions) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.name is not None: u = save_relative_uri(self.name, base_url, True, None, relative_uris) r["name"] = u if self.symbols is not None: u = save_relative_uri(self.symbols, self.name, True, None, relative_uris) r["symbols"] = u if self.type_ is not None: r["type"] = save( self.type_, top=False, base_url=self.name, relative_uris=relative_uris ) if self.label is not None: r["label"] = save( self.label, top=False, base_url=self.name, relative_uris=relative_uris ) if self.doc is not None: r["doc"] = save( self.doc, top=False, base_url=self.name, relative_uris=relative_uris ) if self.inputBinding is not None: r["inputBinding"] = save( self.inputBinding, top=False, base_url=self.name, relative_uris=relative_uris, ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["name", "symbols", "type", "label", "doc", "inputBinding"]) class CommandInputArraySchema( InputArraySchema, CommandInputSchema, CommandLineBindable ): name: str def __init__( self, items: Any, type_: Any, label: Optional[Any] = None, doc: Optional[Any] = None, name: Optional[Any] = None, inputBinding: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.items = items self.type_ = type_ self.label = label self.doc = doc self.name = name if name is not None else "_:" + str(_uuid__.uuid4()) self.inputBinding = inputBinding def __eq__(self, other: Any) -> bool: if isinstance(other, CommandInputArraySchema): return bool( self.items == other.items and self.type_ == other.type_ and self.label == other.label and self.doc == other.doc and self.name == other.name and self.inputBinding == other.inputBinding ) return False def __hash__(self) -> int: return hash( (self.items, self.type_, self.label, self.doc, self.name, self.inputBinding) ) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "CommandInputArraySchema": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] name = None if "name" in _doc: try: name = load_field( _doc.get("name"), uri_union_of_None_type_or_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("name") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `name`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("name") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [e], detailed_message=f"the `name` field with value `{val}` " "is not valid because:", ) ) __original_name_is_none = name is None if name is None: if docRoot is not None: name = docRoot else: name = "_:" + str(_uuid__.uuid4()) if not __original_name_is_none: baseuri = cast(str, name) try: if _doc.get("items") is None: raise ValidationException("missing required field `items`", None, []) items = load_field( _doc.get("items"), uri_union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype_False_True_2_None, baseuri, loadingOptions, lc=_doc.get("items") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `items`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("items") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `items` field is not valid because:", SourceLine(_doc, "items", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `items` field is not valid because:", SourceLine(_doc, "items", str), [e], detailed_message=f"the `items` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("type") is None: raise ValidationException("missing required field `type`", None, []) type_ = load_field( _doc.get("type"), typedsl_Array_nameLoader_2, baseuri, loadingOptions, lc=_doc.get("type") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `type`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("type") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [e], detailed_message=f"the `type` field with value `{val}` " "is not valid because:", ) ) label = None if "label" in _doc: try: label = load_field( _doc.get("label"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("label") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `label`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("label") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [e], detailed_message=f"the `label` field with value `{val}` " "is not valid because:", ) ) doc = None if "doc" in _doc: try: doc = load_field( _doc.get("doc"), union_of_None_type_or_strtype_or_array_of_strtype, baseuri, loadingOptions, lc=_doc.get("doc") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `doc`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("doc") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [e], detailed_message=f"the `doc` field with value `{val}` " "is not valid because:", ) ) inputBinding = None if "inputBinding" in _doc: try: inputBinding = load_field( _doc.get("inputBinding"), union_of_None_type_or_CommandLineBindingLoader, baseuri, loadingOptions, lc=_doc.get("inputBinding") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `inputBinding`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("inputBinding") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `inputBinding` field is not valid because:", SourceLine(_doc, "inputBinding", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `inputBinding` field is not valid because:", SourceLine(_doc, "inputBinding", str), [e], detailed_message=f"the `inputBinding` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `items`, `type`, `label`, `doc`, `name`, `inputBinding`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( items=items, type_=type_, label=label, doc=doc, name=name, inputBinding=inputBinding, extension_fields=extension_fields, loadingOptions=loadingOptions, ) loadingOptions.idx[cast(str, name)] = (_constructed, loadingOptions) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.name is not None: u = save_relative_uri(self.name, base_url, True, None, relative_uris) r["name"] = u if self.items is not None: u = save_relative_uri(self.items, self.name, False, 2, relative_uris) r["items"] = u if self.type_ is not None: r["type"] = save( self.type_, top=False, base_url=self.name, relative_uris=relative_uris ) if self.label is not None: r["label"] = save( self.label, top=False, base_url=self.name, relative_uris=relative_uris ) if self.doc is not None: r["doc"] = save( self.doc, top=False, base_url=self.name, relative_uris=relative_uris ) if self.inputBinding is not None: r["inputBinding"] = save( self.inputBinding, top=False, base_url=self.name, relative_uris=relative_uris, ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["items", "type", "label", "doc", "name", "inputBinding"]) class CommandOutputRecordField(OutputRecordField): name: str def __init__( self, name: Any, type_: Any, doc: Optional[Any] = None, label: Optional[Any] = None, secondaryFiles: Optional[Any] = None, streamable: Optional[Any] = None, format: Optional[Any] = None, outputBinding: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.doc = doc self.name = name if name is not None else "_:" + str(_uuid__.uuid4()) self.type_ = type_ self.label = label self.secondaryFiles = secondaryFiles self.streamable = streamable self.format = format self.outputBinding = outputBinding def __eq__(self, other: Any) -> bool: if isinstance(other, CommandOutputRecordField): return bool( self.doc == other.doc and self.name == other.name and self.type_ == other.type_ and self.label == other.label and self.secondaryFiles == other.secondaryFiles and self.streamable == other.streamable and self.format == other.format and self.outputBinding == other.outputBinding ) return False def __hash__(self) -> int: return hash( ( self.doc, self.name, self.type_, self.label, self.secondaryFiles, self.streamable, self.format, self.outputBinding, ) ) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "CommandOutputRecordField": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] name = None if "name" in _doc: try: name = load_field( _doc.get("name"), uri_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("name") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `name`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("name") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [e], detailed_message=f"the `name` field with value `{val}` " "is not valid because:", ) ) __original_name_is_none = name is None if name is None: if docRoot is not None: name = docRoot else: _errors__.append(ValidationException("missing name")) if not __original_name_is_none: baseuri = cast(str, name) doc = None if "doc" in _doc: try: doc = load_field( _doc.get("doc"), union_of_None_type_or_strtype_or_array_of_strtype, baseuri, loadingOptions, lc=_doc.get("doc") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `doc`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("doc") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [e], detailed_message=f"the `doc` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("type") is None: raise ValidationException("missing required field `type`", None, []) type_ = load_field( _doc.get("type"), typedsl_union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype_2, baseuri, loadingOptions, lc=_doc.get("type") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `type`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("type") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [e], detailed_message=f"the `type` field with value `{val}` " "is not valid because:", ) ) label = None if "label" in _doc: try: label = load_field( _doc.get("label"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("label") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `label`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("label") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [e], detailed_message=f"the `label` field with value `{val}` " "is not valid because:", ) ) secondaryFiles = None if "secondaryFiles" in _doc: try: secondaryFiles = load_field( _doc.get("secondaryFiles"), secondaryfilesdsl_union_of_None_type_or_SecondaryFileSchemaLoader_or_array_of_SecondaryFileSchemaLoader, baseuri, loadingOptions, lc=_doc.get("secondaryFiles") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `secondaryFiles`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("secondaryFiles") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `secondaryFiles` field is not valid because:", SourceLine(_doc, "secondaryFiles", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `secondaryFiles` field is not valid because:", SourceLine(_doc, "secondaryFiles", str), [e], detailed_message=f"the `secondaryFiles` field with value `{val}` " "is not valid because:", ) ) streamable = None if "streamable" in _doc: try: streamable = load_field( _doc.get("streamable"), union_of_None_type_or_booltype, baseuri, loadingOptions, lc=_doc.get("streamable") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `streamable`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("streamable") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `streamable` field is not valid because:", SourceLine(_doc, "streamable", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `streamable` field is not valid because:", SourceLine(_doc, "streamable", str), [e], detailed_message=f"the `streamable` field with value `{val}` " "is not valid because:", ) ) format = None if "format" in _doc: try: format = load_field( _doc.get("format"), uri_union_of_None_type_or_strtype_or_ExpressionLoader_True_False_None_True, baseuri, loadingOptions, lc=_doc.get("format") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `format`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("format") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `format` field is not valid because:", SourceLine(_doc, "format", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `format` field is not valid because:", SourceLine(_doc, "format", str), [e], detailed_message=f"the `format` field with value `{val}` " "is not valid because:", ) ) outputBinding = None if "outputBinding" in _doc: try: outputBinding = load_field( _doc.get("outputBinding"), union_of_None_type_or_CommandOutputBindingLoader, baseuri, loadingOptions, lc=_doc.get("outputBinding") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `outputBinding`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("outputBinding") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `outputBinding` field is not valid because:", SourceLine(_doc, "outputBinding", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `outputBinding` field is not valid because:", SourceLine(_doc, "outputBinding", str), [e], detailed_message=f"the `outputBinding` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `doc`, `name`, `type`, `label`, `secondaryFiles`, `streamable`, `format`, `outputBinding`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( doc=doc, name=name, type_=type_, label=label, secondaryFiles=secondaryFiles, streamable=streamable, format=format, outputBinding=outputBinding, extension_fields=extension_fields, loadingOptions=loadingOptions, ) loadingOptions.idx[cast(str, name)] = (_constructed, loadingOptions) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.name is not None: u = save_relative_uri(self.name, base_url, True, None, relative_uris) r["name"] = u if self.doc is not None: r["doc"] = save( self.doc, top=False, base_url=self.name, relative_uris=relative_uris ) if self.type_ is not None: r["type"] = save( self.type_, top=False, base_url=self.name, relative_uris=relative_uris ) if self.label is not None: r["label"] = save( self.label, top=False, base_url=self.name, relative_uris=relative_uris ) if self.secondaryFiles is not None: r["secondaryFiles"] = save( self.secondaryFiles, top=False, base_url=self.name, relative_uris=relative_uris, ) if self.streamable is not None: r["streamable"] = save( self.streamable, top=False, base_url=self.name, relative_uris=relative_uris, ) if self.format is not None: u = save_relative_uri(self.format, self.name, True, None, relative_uris) r["format"] = u if self.outputBinding is not None: r["outputBinding"] = save( self.outputBinding, top=False, base_url=self.name, relative_uris=relative_uris, ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset( [ "doc", "name", "type", "label", "secondaryFiles", "streamable", "format", "outputBinding", ] ) class CommandOutputRecordSchema(OutputRecordSchema): name: str def __init__( self, type_: Any, fields: Optional[Any] = None, label: Optional[Any] = None, doc: Optional[Any] = None, name: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.fields = fields self.type_ = type_ self.label = label self.doc = doc self.name = name if name is not None else "_:" + str(_uuid__.uuid4()) def __eq__(self, other: Any) -> bool: if isinstance(other, CommandOutputRecordSchema): return bool( self.fields == other.fields and self.type_ == other.type_ and self.label == other.label and self.doc == other.doc and self.name == other.name ) return False def __hash__(self) -> int: return hash((self.fields, self.type_, self.label, self.doc, self.name)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "CommandOutputRecordSchema": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] name = None if "name" in _doc: try: name = load_field( _doc.get("name"), uri_union_of_None_type_or_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("name") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `name`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("name") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [e], detailed_message=f"the `name` field with value `{val}` " "is not valid because:", ) ) __original_name_is_none = name is None if name is None: if docRoot is not None: name = docRoot else: name = "_:" + str(_uuid__.uuid4()) if not __original_name_is_none: baseuri = cast(str, name) fields = None if "fields" in _doc: try: fields = load_field( _doc.get("fields"), idmap_fields_union_of_None_type_or_array_of_CommandOutputRecordFieldLoader, baseuri, loadingOptions, lc=_doc.get("fields") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `fields`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("fields") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `fields` field is not valid because:", SourceLine(_doc, "fields", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `fields` field is not valid because:", SourceLine(_doc, "fields", str), [e], detailed_message=f"the `fields` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("type") is None: raise ValidationException("missing required field `type`", None, []) type_ = load_field( _doc.get("type"), typedsl_Record_nameLoader_2, baseuri, loadingOptions, lc=_doc.get("type") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `type`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("type") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [e], detailed_message=f"the `type` field with value `{val}` " "is not valid because:", ) ) label = None if "label" in _doc: try: label = load_field( _doc.get("label"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("label") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `label`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("label") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [e], detailed_message=f"the `label` field with value `{val}` " "is not valid because:", ) ) doc = None if "doc" in _doc: try: doc = load_field( _doc.get("doc"), union_of_None_type_or_strtype_or_array_of_strtype, baseuri, loadingOptions, lc=_doc.get("doc") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `doc`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("doc") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [e], detailed_message=f"the `doc` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `fields`, `type`, `label`, `doc`, `name`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( fields=fields, type_=type_, label=label, doc=doc, name=name, extension_fields=extension_fields, loadingOptions=loadingOptions, ) loadingOptions.idx[cast(str, name)] = (_constructed, loadingOptions) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.name is not None: u = save_relative_uri(self.name, base_url, True, None, relative_uris) r["name"] = u if self.fields is not None: r["fields"] = save( self.fields, top=False, base_url=self.name, relative_uris=relative_uris ) if self.type_ is not None: r["type"] = save( self.type_, top=False, base_url=self.name, relative_uris=relative_uris ) if self.label is not None: r["label"] = save( self.label, top=False, base_url=self.name, relative_uris=relative_uris ) if self.doc is not None: r["doc"] = save( self.doc, top=False, base_url=self.name, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["fields", "type", "label", "doc", "name"]) class CommandOutputEnumSchema(OutputEnumSchema): name: str def __init__( self, symbols: Any, type_: Any, name: Optional[Any] = None, label: Optional[Any] = None, doc: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.name = name if name is not None else "_:" + str(_uuid__.uuid4()) self.symbols = symbols self.type_ = type_ self.label = label self.doc = doc def __eq__(self, other: Any) -> bool: if isinstance(other, CommandOutputEnumSchema): return bool( self.name == other.name and self.symbols == other.symbols and self.type_ == other.type_ and self.label == other.label and self.doc == other.doc ) return False def __hash__(self) -> int: return hash((self.name, self.symbols, self.type_, self.label, self.doc)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "CommandOutputEnumSchema": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] name = None if "name" in _doc: try: name = load_field( _doc.get("name"), uri_union_of_None_type_or_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("name") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `name`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("name") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [e], detailed_message=f"the `name` field with value `{val}` " "is not valid because:", ) ) __original_name_is_none = name is None if name is None: if docRoot is not None: name = docRoot else: name = "_:" + str(_uuid__.uuid4()) if not __original_name_is_none: baseuri = cast(str, name) try: if _doc.get("symbols") is None: raise ValidationException("missing required field `symbols`", None, []) symbols = load_field( _doc.get("symbols"), uri_array_of_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("symbols") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `symbols`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("symbols") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `symbols` field is not valid because:", SourceLine(_doc, "symbols", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `symbols` field is not valid because:", SourceLine(_doc, "symbols", str), [e], detailed_message=f"the `symbols` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("type") is None: raise ValidationException("missing required field `type`", None, []) type_ = load_field( _doc.get("type"), typedsl_Enum_nameLoader_2, baseuri, loadingOptions, lc=_doc.get("type") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `type`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("type") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [e], detailed_message=f"the `type` field with value `{val}` " "is not valid because:", ) ) label = None if "label" in _doc: try: label = load_field( _doc.get("label"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("label") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `label`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("label") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [e], detailed_message=f"the `label` field with value `{val}` " "is not valid because:", ) ) doc = None if "doc" in _doc: try: doc = load_field( _doc.get("doc"), union_of_None_type_or_strtype_or_array_of_strtype, baseuri, loadingOptions, lc=_doc.get("doc") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `doc`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("doc") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [e], detailed_message=f"the `doc` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `name`, `symbols`, `type`, `label`, `doc`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( name=name, symbols=symbols, type_=type_, label=label, doc=doc, extension_fields=extension_fields, loadingOptions=loadingOptions, ) loadingOptions.idx[cast(str, name)] = (_constructed, loadingOptions) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.name is not None: u = save_relative_uri(self.name, base_url, True, None, relative_uris) r["name"] = u if self.symbols is not None: u = save_relative_uri(self.symbols, self.name, True, None, relative_uris) r["symbols"] = u if self.type_ is not None: r["type"] = save( self.type_, top=False, base_url=self.name, relative_uris=relative_uris ) if self.label is not None: r["label"] = save( self.label, top=False, base_url=self.name, relative_uris=relative_uris ) if self.doc is not None: r["doc"] = save( self.doc, top=False, base_url=self.name, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["name", "symbols", "type", "label", "doc"]) class CommandOutputArraySchema(OutputArraySchema): name: str def __init__( self, items: Any, type_: Any, label: Optional[Any] = None, doc: Optional[Any] = None, name: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.items = items self.type_ = type_ self.label = label self.doc = doc self.name = name if name is not None else "_:" + str(_uuid__.uuid4()) def __eq__(self, other: Any) -> bool: if isinstance(other, CommandOutputArraySchema): return bool( self.items == other.items and self.type_ == other.type_ and self.label == other.label and self.doc == other.doc and self.name == other.name ) return False def __hash__(self) -> int: return hash((self.items, self.type_, self.label, self.doc, self.name)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "CommandOutputArraySchema": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] name = None if "name" in _doc: try: name = load_field( _doc.get("name"), uri_union_of_None_type_or_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("name") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `name`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("name") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `name` field is not valid because:", SourceLine(_doc, "name", str), [e], detailed_message=f"the `name` field with value `{val}` " "is not valid because:", ) ) __original_name_is_none = name is None if name is None: if docRoot is not None: name = docRoot else: name = "_:" + str(_uuid__.uuid4()) if not __original_name_is_none: baseuri = cast(str, name) try: if _doc.get("items") is None: raise ValidationException("missing required field `items`", None, []) items = load_field( _doc.get("items"), uri_union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype_False_True_2_None, baseuri, loadingOptions, lc=_doc.get("items") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `items`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("items") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `items` field is not valid because:", SourceLine(_doc, "items", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `items` field is not valid because:", SourceLine(_doc, "items", str), [e], detailed_message=f"the `items` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("type") is None: raise ValidationException("missing required field `type`", None, []) type_ = load_field( _doc.get("type"), typedsl_Array_nameLoader_2, baseuri, loadingOptions, lc=_doc.get("type") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `type`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("type") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [e], detailed_message=f"the `type` field with value `{val}` " "is not valid because:", ) ) label = None if "label" in _doc: try: label = load_field( _doc.get("label"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("label") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `label`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("label") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [e], detailed_message=f"the `label` field with value `{val}` " "is not valid because:", ) ) doc = None if "doc" in _doc: try: doc = load_field( _doc.get("doc"), union_of_None_type_or_strtype_or_array_of_strtype, baseuri, loadingOptions, lc=_doc.get("doc") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `doc`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("doc") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [e], detailed_message=f"the `doc` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `items`, `type`, `label`, `doc`, `name`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( items=items, type_=type_, label=label, doc=doc, name=name, extension_fields=extension_fields, loadingOptions=loadingOptions, ) loadingOptions.idx[cast(str, name)] = (_constructed, loadingOptions) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.name is not None: u = save_relative_uri(self.name, base_url, True, None, relative_uris) r["name"] = u if self.items is not None: u = save_relative_uri(self.items, self.name, False, 2, relative_uris) r["items"] = u if self.type_ is not None: r["type"] = save( self.type_, top=False, base_url=self.name, relative_uris=relative_uris ) if self.label is not None: r["label"] = save( self.label, top=False, base_url=self.name, relative_uris=relative_uris ) if self.doc is not None: r["doc"] = save( self.doc, top=False, base_url=self.name, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["items", "type", "label", "doc", "name"]) class CommandInputParameter(InputParameter): """ An input parameter for a CommandLineTool. """ id: str def __init__( self, id: Any, type_: Any, label: Optional[Any] = None, secondaryFiles: Optional[Any] = None, streamable: Optional[Any] = None, doc: Optional[Any] = None, format: Optional[Any] = None, loadContents: Optional[Any] = None, loadListing: Optional[Any] = None, default: Optional[Any] = None, inputBinding: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.label = label self.secondaryFiles = secondaryFiles self.streamable = streamable self.doc = doc self.id = id if id is not None else "_:" + str(_uuid__.uuid4()) self.format = format self.loadContents = loadContents self.loadListing = loadListing self.default = default self.type_ = type_ self.inputBinding = inputBinding def __eq__(self, other: Any) -> bool: if isinstance(other, CommandInputParameter): return bool( self.label == other.label and self.secondaryFiles == other.secondaryFiles and self.streamable == other.streamable and self.doc == other.doc and self.id == other.id and self.format == other.format and self.loadContents == other.loadContents and self.loadListing == other.loadListing and self.default == other.default and self.type_ == other.type_ and self.inputBinding == other.inputBinding ) return False def __hash__(self) -> int: return hash( ( self.label, self.secondaryFiles, self.streamable, self.doc, self.id, self.format, self.loadContents, self.loadListing, self.default, self.type_, self.inputBinding, ) ) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "CommandInputParameter": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] id = None if "id" in _doc: try: id = load_field( _doc.get("id"), uri_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("id") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `id`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("id") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `id` field is not valid because:", SourceLine(_doc, "id", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `id` field is not valid because:", SourceLine(_doc, "id", str), [e], detailed_message=f"the `id` field with value `{val}` " "is not valid because:", ) ) __original_id_is_none = id is None if id is None: if docRoot is not None: id = docRoot else: _errors__.append(ValidationException("missing id")) if not __original_id_is_none: baseuri = cast(str, id) label = None if "label" in _doc: try: label = load_field( _doc.get("label"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("label") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `label`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("label") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [e], detailed_message=f"the `label` field with value `{val}` " "is not valid because:", ) ) secondaryFiles = None if "secondaryFiles" in _doc: try: secondaryFiles = load_field( _doc.get("secondaryFiles"), secondaryfilesdsl_union_of_None_type_or_SecondaryFileSchemaLoader_or_array_of_SecondaryFileSchemaLoader, baseuri, loadingOptions, lc=_doc.get("secondaryFiles") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `secondaryFiles`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("secondaryFiles") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `secondaryFiles` field is not valid because:", SourceLine(_doc, "secondaryFiles", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `secondaryFiles` field is not valid because:", SourceLine(_doc, "secondaryFiles", str), [e], detailed_message=f"the `secondaryFiles` field with value `{val}` " "is not valid because:", ) ) streamable = None if "streamable" in _doc: try: streamable = load_field( _doc.get("streamable"), union_of_None_type_or_booltype, baseuri, loadingOptions, lc=_doc.get("streamable") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `streamable`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("streamable") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `streamable` field is not valid because:", SourceLine(_doc, "streamable", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `streamable` field is not valid because:", SourceLine(_doc, "streamable", str), [e], detailed_message=f"the `streamable` field with value `{val}` " "is not valid because:", ) ) doc = None if "doc" in _doc: try: doc = load_field( _doc.get("doc"), union_of_None_type_or_strtype_or_array_of_strtype, baseuri, loadingOptions, lc=_doc.get("doc") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `doc`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("doc") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [e], detailed_message=f"the `doc` field with value `{val}` " "is not valid because:", ) ) format = None if "format" in _doc: try: format = load_field( _doc.get("format"), uri_union_of_None_type_or_strtype_or_array_of_strtype_or_ExpressionLoader_True_False_None_True, baseuri, loadingOptions, lc=_doc.get("format") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `format`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("format") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `format` field is not valid because:", SourceLine(_doc, "format", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `format` field is not valid because:", SourceLine(_doc, "format", str), [e], detailed_message=f"the `format` field with value `{val}` " "is not valid because:", ) ) loadContents = None if "loadContents" in _doc: try: loadContents = load_field( _doc.get("loadContents"), union_of_None_type_or_booltype, baseuri, loadingOptions, lc=_doc.get("loadContents") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `loadContents`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("loadContents") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `loadContents` field is not valid because:", SourceLine(_doc, "loadContents", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `loadContents` field is not valid because:", SourceLine(_doc, "loadContents", str), [e], detailed_message=f"the `loadContents` field with value `{val}` " "is not valid because:", ) ) loadListing = None if "loadListing" in _doc: try: loadListing = load_field( _doc.get("loadListing"), union_of_None_type_or_LoadListingEnumLoader, baseuri, loadingOptions, lc=_doc.get("loadListing") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `loadListing`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("loadListing") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `loadListing` field is not valid because:", SourceLine(_doc, "loadListing", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `loadListing` field is not valid because:", SourceLine(_doc, "loadListing", str), [e], detailed_message=f"the `loadListing` field with value `{val}` " "is not valid because:", ) ) default = None if "default" in _doc: try: default = load_field( _doc.get("default"), union_of_None_type_or_CWLObjectTypeLoader, baseuri, loadingOptions, lc=_doc.get("default") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `default`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("default") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `default` field is not valid because:", SourceLine(_doc, "default", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `default` field is not valid because:", SourceLine(_doc, "default", str), [e], detailed_message=f"the `default` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("type") is None: raise ValidationException("missing required field `type`", None, []) type_ = load_field( _doc.get("type"), typedsl_union_of_CWLTypeLoader_or_stdinLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype_2, baseuri, loadingOptions, lc=_doc.get("type") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `type`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("type") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [e], detailed_message=f"the `type` field with value `{val}` " "is not valid because:", ) ) inputBinding = None if "inputBinding" in _doc: try: inputBinding = load_field( _doc.get("inputBinding"), union_of_None_type_or_CommandLineBindingLoader, baseuri, loadingOptions, lc=_doc.get("inputBinding") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `inputBinding`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("inputBinding") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `inputBinding` field is not valid because:", SourceLine(_doc, "inputBinding", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `inputBinding` field is not valid because:", SourceLine(_doc, "inputBinding", str), [e], detailed_message=f"the `inputBinding` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `label`, `secondaryFiles`, `streamable`, `doc`, `id`, `format`, `loadContents`, `loadListing`, `default`, `type`, `inputBinding`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( label=label, secondaryFiles=secondaryFiles, streamable=streamable, doc=doc, id=id, format=format, loadContents=loadContents, loadListing=loadListing, default=default, type_=type_, inputBinding=inputBinding, extension_fields=extension_fields, loadingOptions=loadingOptions, ) loadingOptions.idx[cast(str, id)] = (_constructed, loadingOptions) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.id is not None: u = save_relative_uri(self.id, base_url, True, None, relative_uris) r["id"] = u if self.label is not None: r["label"] = save( self.label, top=False, base_url=self.id, relative_uris=relative_uris ) if self.secondaryFiles is not None: r["secondaryFiles"] = save( self.secondaryFiles, top=False, base_url=self.id, relative_uris=relative_uris, ) if self.streamable is not None: r["streamable"] = save( self.streamable, top=False, base_url=self.id, relative_uris=relative_uris, ) if self.doc is not None: r["doc"] = save( self.doc, top=False, base_url=self.id, relative_uris=relative_uris ) if self.format is not None: u = save_relative_uri(self.format, self.id, True, None, relative_uris) r["format"] = u if self.loadContents is not None: r["loadContents"] = save( self.loadContents, top=False, base_url=self.id, relative_uris=relative_uris, ) if self.loadListing is not None: r["loadListing"] = save( self.loadListing, top=False, base_url=self.id, relative_uris=relative_uris, ) if self.default is not None: r["default"] = save( self.default, top=False, base_url=self.id, relative_uris=relative_uris ) if self.type_ is not None: r["type"] = save( self.type_, top=False, base_url=self.id, relative_uris=relative_uris ) if self.inputBinding is not None: r["inputBinding"] = save( self.inputBinding, top=False, base_url=self.id, relative_uris=relative_uris, ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset( [ "label", "secondaryFiles", "streamable", "doc", "id", "format", "loadContents", "loadListing", "default", "type", "inputBinding", ] ) class CommandOutputParameter(OutputParameter): """ An output parameter for a CommandLineTool. """ id: str def __init__( self, id: Any, type_: Any, label: Optional[Any] = None, secondaryFiles: Optional[Any] = None, streamable: Optional[Any] = None, doc: Optional[Any] = None, format: Optional[Any] = None, outputBinding: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.label = label self.secondaryFiles = secondaryFiles self.streamable = streamable self.doc = doc self.id = id if id is not None else "_:" + str(_uuid__.uuid4()) self.format = format self.type_ = type_ self.outputBinding = outputBinding def __eq__(self, other: Any) -> bool: if isinstance(other, CommandOutputParameter): return bool( self.label == other.label and self.secondaryFiles == other.secondaryFiles and self.streamable == other.streamable and self.doc == other.doc and self.id == other.id and self.format == other.format and self.type_ == other.type_ and self.outputBinding == other.outputBinding ) return False def __hash__(self) -> int: return hash( ( self.label, self.secondaryFiles, self.streamable, self.doc, self.id, self.format, self.type_, self.outputBinding, ) ) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "CommandOutputParameter": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] id = None if "id" in _doc: try: id = load_field( _doc.get("id"), uri_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("id") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `id`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("id") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `id` field is not valid because:", SourceLine(_doc, "id", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `id` field is not valid because:", SourceLine(_doc, "id", str), [e], detailed_message=f"the `id` field with value `{val}` " "is not valid because:", ) ) __original_id_is_none = id is None if id is None: if docRoot is not None: id = docRoot else: _errors__.append(ValidationException("missing id")) if not __original_id_is_none: baseuri = cast(str, id) label = None if "label" in _doc: try: label = load_field( _doc.get("label"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("label") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `label`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("label") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [e], detailed_message=f"the `label` field with value `{val}` " "is not valid because:", ) ) secondaryFiles = None if "secondaryFiles" in _doc: try: secondaryFiles = load_field( _doc.get("secondaryFiles"), secondaryfilesdsl_union_of_None_type_or_SecondaryFileSchemaLoader_or_array_of_SecondaryFileSchemaLoader, baseuri, loadingOptions, lc=_doc.get("secondaryFiles") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `secondaryFiles`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("secondaryFiles") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `secondaryFiles` field is not valid because:", SourceLine(_doc, "secondaryFiles", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `secondaryFiles` field is not valid because:", SourceLine(_doc, "secondaryFiles", str), [e], detailed_message=f"the `secondaryFiles` field with value `{val}` " "is not valid because:", ) ) streamable = None if "streamable" in _doc: try: streamable = load_field( _doc.get("streamable"), union_of_None_type_or_booltype, baseuri, loadingOptions, lc=_doc.get("streamable") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `streamable`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("streamable") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `streamable` field is not valid because:", SourceLine(_doc, "streamable", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `streamable` field is not valid because:", SourceLine(_doc, "streamable", str), [e], detailed_message=f"the `streamable` field with value `{val}` " "is not valid because:", ) ) doc = None if "doc" in _doc: try: doc = load_field( _doc.get("doc"), union_of_None_type_or_strtype_or_array_of_strtype, baseuri, loadingOptions, lc=_doc.get("doc") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `doc`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("doc") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [e], detailed_message=f"the `doc` field with value `{val}` " "is not valid because:", ) ) format = None if "format" in _doc: try: format = load_field( _doc.get("format"), uri_union_of_None_type_or_strtype_or_ExpressionLoader_True_False_None_True, baseuri, loadingOptions, lc=_doc.get("format") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `format`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("format") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `format` field is not valid because:", SourceLine(_doc, "format", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `format` field is not valid because:", SourceLine(_doc, "format", str), [e], detailed_message=f"the `format` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("type") is None: raise ValidationException("missing required field `type`", None, []) type_ = load_field( _doc.get("type"), typedsl_union_of_CWLTypeLoader_or_stdoutLoader_or_stderrLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype_2, baseuri, loadingOptions, lc=_doc.get("type") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `type`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("type") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [e], detailed_message=f"the `type` field with value `{val}` " "is not valid because:", ) ) outputBinding = None if "outputBinding" in _doc: try: outputBinding = load_field( _doc.get("outputBinding"), union_of_None_type_or_CommandOutputBindingLoader, baseuri, loadingOptions, lc=_doc.get("outputBinding") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `outputBinding`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("outputBinding") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `outputBinding` field is not valid because:", SourceLine(_doc, "outputBinding", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `outputBinding` field is not valid because:", SourceLine(_doc, "outputBinding", str), [e], detailed_message=f"the `outputBinding` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `label`, `secondaryFiles`, `streamable`, `doc`, `id`, `format`, `type`, `outputBinding`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( label=label, secondaryFiles=secondaryFiles, streamable=streamable, doc=doc, id=id, format=format, type_=type_, outputBinding=outputBinding, extension_fields=extension_fields, loadingOptions=loadingOptions, ) loadingOptions.idx[cast(str, id)] = (_constructed, loadingOptions) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.id is not None: u = save_relative_uri(self.id, base_url, True, None, relative_uris) r["id"] = u if self.label is not None: r["label"] = save( self.label, top=False, base_url=self.id, relative_uris=relative_uris ) if self.secondaryFiles is not None: r["secondaryFiles"] = save( self.secondaryFiles, top=False, base_url=self.id, relative_uris=relative_uris, ) if self.streamable is not None: r["streamable"] = save( self.streamable, top=False, base_url=self.id, relative_uris=relative_uris, ) if self.doc is not None: r["doc"] = save( self.doc, top=False, base_url=self.id, relative_uris=relative_uris ) if self.format is not None: u = save_relative_uri(self.format, self.id, True, None, relative_uris) r["format"] = u if self.type_ is not None: r["type"] = save( self.type_, top=False, base_url=self.id, relative_uris=relative_uris ) if self.outputBinding is not None: r["outputBinding"] = save( self.outputBinding, top=False, base_url=self.id, relative_uris=relative_uris, ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset( [ "label", "secondaryFiles", "streamable", "doc", "id", "format", "type", "outputBinding", ] ) class CommandLineTool(Process): """ This defines the schema of the CWL Command Line Tool Description document. """ id: str def __init__( self, inputs: Any, outputs: Any, id: Optional[Any] = None, label: Optional[Any] = None, doc: Optional[Any] = None, requirements: Optional[Any] = None, hints: Optional[Any] = None, cwlVersion: Optional[Any] = None, intent: Optional[Any] = None, baseCommand: Optional[Any] = None, arguments: Optional[Any] = None, stdin: Optional[Any] = None, stderr: Optional[Any] = None, stdout: Optional[Any] = None, successCodes: Optional[Any] = None, temporaryFailCodes: Optional[Any] = None, permanentFailCodes: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.id = id if id is not None else "_:" + str(_uuid__.uuid4()) self.label = label self.doc = doc self.inputs = inputs self.outputs = outputs self.requirements = requirements self.hints = hints self.cwlVersion = cwlVersion self.intent = intent self.class_ = "CommandLineTool" self.baseCommand = baseCommand self.arguments = arguments self.stdin = stdin self.stderr = stderr self.stdout = stdout self.successCodes = successCodes self.temporaryFailCodes = temporaryFailCodes self.permanentFailCodes = permanentFailCodes def __eq__(self, other: Any) -> bool: if isinstance(other, CommandLineTool): return bool( self.id == other.id and self.label == other.label and self.doc == other.doc and self.inputs == other.inputs and self.outputs == other.outputs and self.requirements == other.requirements and self.hints == other.hints and self.cwlVersion == other.cwlVersion and self.intent == other.intent and self.class_ == other.class_ and self.baseCommand == other.baseCommand and self.arguments == other.arguments and self.stdin == other.stdin and self.stderr == other.stderr and self.stdout == other.stdout and self.successCodes == other.successCodes and self.temporaryFailCodes == other.temporaryFailCodes and self.permanentFailCodes == other.permanentFailCodes ) return False def __hash__(self) -> int: return hash( ( self.id, self.label, self.doc, self.inputs, self.outputs, self.requirements, self.hints, self.cwlVersion, self.intent, self.class_, self.baseCommand, self.arguments, self.stdin, self.stderr, self.stdout, self.successCodes, self.temporaryFailCodes, self.permanentFailCodes, ) ) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "CommandLineTool": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] id = None if "id" in _doc: try: id = load_field( _doc.get("id"), uri_union_of_None_type_or_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("id") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `id`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("id") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `id` field is not valid because:", SourceLine(_doc, "id", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `id` field is not valid because:", SourceLine(_doc, "id", str), [e], detailed_message=f"the `id` field with value `{val}` " "is not valid because:", ) ) __original_id_is_none = id is None if id is None: if docRoot is not None: id = docRoot else: id = "_:" + str(_uuid__.uuid4()) if not __original_id_is_none: baseuri = cast(str, id) try: if _doc.get("class") is None: raise ValidationException("missing required field `class`", None, []) class_ = load_field( _doc.get("class"), uri_CommandLineTool_classLoader_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("class") ) if class_ not in (cls.__name__, loadingOptions.vocab.get(cls.__name__)): raise ValidationException(f"tried `{cls.__name__}` but") except ValidationException as e: raise e label = None if "label" in _doc: try: label = load_field( _doc.get("label"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("label") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `label`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("label") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [e], detailed_message=f"the `label` field with value `{val}` " "is not valid because:", ) ) doc = None if "doc" in _doc: try: doc = load_field( _doc.get("doc"), union_of_None_type_or_strtype_or_array_of_strtype, baseuri, loadingOptions, lc=_doc.get("doc") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `doc`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("doc") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [e], detailed_message=f"the `doc` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("inputs") is None: raise ValidationException("missing required field `inputs`", None, []) inputs = load_field( _doc.get("inputs"), idmap_inputs_array_of_CommandInputParameterLoader, baseuri, loadingOptions, lc=_doc.get("inputs") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `inputs`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("inputs") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `inputs` field is not valid because:", SourceLine(_doc, "inputs", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `inputs` field is not valid because:", SourceLine(_doc, "inputs", str), [e], detailed_message=f"the `inputs` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("outputs") is None: raise ValidationException("missing required field `outputs`", None, []) outputs = load_field( _doc.get("outputs"), idmap_outputs_array_of_CommandOutputParameterLoader, baseuri, loadingOptions, lc=_doc.get("outputs") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `outputs`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("outputs") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `outputs` field is not valid because:", SourceLine(_doc, "outputs", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `outputs` field is not valid because:", SourceLine(_doc, "outputs", str), [e], detailed_message=f"the `outputs` field with value `{val}` " "is not valid because:", ) ) requirements = None if "requirements" in _doc: try: requirements = load_field( _doc.get("requirements"), idmap_requirements_union_of_None_type_or_array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_LoadListingRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_WorkReuseLoader_or_NetworkAccessLoader_or_InplaceUpdateRequirementLoader_or_ToolTimeLimitLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader_or_SecretsLoader_or_MPIRequirementLoader_or_CUDARequirementLoader_or_LoopLoader_or_ShmSizeLoader, baseuri, loadingOptions, lc=_doc.get("requirements") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `requirements`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("requirements") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `requirements` field is not valid because:", SourceLine(_doc, "requirements", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `requirements` field is not valid because:", SourceLine(_doc, "requirements", str), [e], detailed_message=f"the `requirements` field with value `{val}` " "is not valid because:", ) ) hints = None if "hints" in _doc: try: hints = load_field( _doc.get("hints"), idmap_hints_union_of_None_type_or_array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_LoadListingRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_WorkReuseLoader_or_NetworkAccessLoader_or_InplaceUpdateRequirementLoader_or_ToolTimeLimitLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader_or_SecretsLoader_or_MPIRequirementLoader_or_CUDARequirementLoader_or_LoopLoader_or_ShmSizeLoader_or_Any_type, baseuri, loadingOptions, lc=_doc.get("hints") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `hints`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("hints") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `hints` field is not valid because:", SourceLine(_doc, "hints", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `hints` field is not valid because:", SourceLine(_doc, "hints", str), [e], detailed_message=f"the `hints` field with value `{val}` " "is not valid because:", ) ) cwlVersion = None if "cwlVersion" in _doc: try: cwlVersion = load_field( _doc.get("cwlVersion"), uri_union_of_None_type_or_CWLVersionLoader_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("cwlVersion") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `cwlVersion`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("cwlVersion") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `cwlVersion` field is not valid because:", SourceLine(_doc, "cwlVersion", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `cwlVersion` field is not valid because:", SourceLine(_doc, "cwlVersion", str), [e], detailed_message=f"the `cwlVersion` field with value `{val}` " "is not valid because:", ) ) intent = None if "intent" in _doc: try: intent = load_field( _doc.get("intent"), uri_union_of_None_type_or_array_of_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("intent") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `intent`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("intent") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `intent` field is not valid because:", SourceLine(_doc, "intent", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `intent` field is not valid because:", SourceLine(_doc, "intent", str), [e], detailed_message=f"the `intent` field with value `{val}` " "is not valid because:", ) ) baseCommand = None if "baseCommand" in _doc: try: baseCommand = load_field( _doc.get("baseCommand"), union_of_None_type_or_strtype_or_array_of_strtype, baseuri, loadingOptions, lc=_doc.get("baseCommand") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `baseCommand`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("baseCommand") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `baseCommand` field is not valid because:", SourceLine(_doc, "baseCommand", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `baseCommand` field is not valid because:", SourceLine(_doc, "baseCommand", str), [e], detailed_message=f"the `baseCommand` field with value `{val}` " "is not valid because:", ) ) arguments = None if "arguments" in _doc: try: arguments = load_field( _doc.get("arguments"), union_of_None_type_or_array_of_union_of_strtype_or_ExpressionLoader_or_CommandLineBindingLoader, baseuri, loadingOptions, lc=_doc.get("arguments") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `arguments`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("arguments") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `arguments` field is not valid because:", SourceLine(_doc, "arguments", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `arguments` field is not valid because:", SourceLine(_doc, "arguments", str), [e], detailed_message=f"the `arguments` field with value `{val}` " "is not valid because:", ) ) stdin = None if "stdin" in _doc: try: stdin = load_field( _doc.get("stdin"), union_of_None_type_or_strtype_or_ExpressionLoader, baseuri, loadingOptions, lc=_doc.get("stdin") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `stdin`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("stdin") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `stdin` field is not valid because:", SourceLine(_doc, "stdin", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `stdin` field is not valid because:", SourceLine(_doc, "stdin", str), [e], detailed_message=f"the `stdin` field with value `{val}` " "is not valid because:", ) ) stderr = None if "stderr" in _doc: try: stderr = load_field( _doc.get("stderr"), union_of_None_type_or_strtype_or_ExpressionLoader, baseuri, loadingOptions, lc=_doc.get("stderr") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `stderr`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("stderr") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `stderr` field is not valid because:", SourceLine(_doc, "stderr", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `stderr` field is not valid because:", SourceLine(_doc, "stderr", str), [e], detailed_message=f"the `stderr` field with value `{val}` " "is not valid because:", ) ) stdout = None if "stdout" in _doc: try: stdout = load_field( _doc.get("stdout"), union_of_None_type_or_strtype_or_ExpressionLoader, baseuri, loadingOptions, lc=_doc.get("stdout") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `stdout`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("stdout") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `stdout` field is not valid because:", SourceLine(_doc, "stdout", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `stdout` field is not valid because:", SourceLine(_doc, "stdout", str), [e], detailed_message=f"the `stdout` field with value `{val}` " "is not valid because:", ) ) successCodes = None if "successCodes" in _doc: try: successCodes = load_field( _doc.get("successCodes"), union_of_None_type_or_array_of_inttype, baseuri, loadingOptions, lc=_doc.get("successCodes") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `successCodes`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("successCodes") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `successCodes` field is not valid because:", SourceLine(_doc, "successCodes", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `successCodes` field is not valid because:", SourceLine(_doc, "successCodes", str), [e], detailed_message=f"the `successCodes` field with value `{val}` " "is not valid because:", ) ) temporaryFailCodes = None if "temporaryFailCodes" in _doc: try: temporaryFailCodes = load_field( _doc.get("temporaryFailCodes"), union_of_None_type_or_array_of_inttype, baseuri, loadingOptions, lc=_doc.get("temporaryFailCodes") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `temporaryFailCodes`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("temporaryFailCodes") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `temporaryFailCodes` field is not valid because:", SourceLine(_doc, "temporaryFailCodes", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `temporaryFailCodes` field is not valid because:", SourceLine(_doc, "temporaryFailCodes", str), [e], detailed_message=f"the `temporaryFailCodes` field with value `{val}` " "is not valid because:", ) ) permanentFailCodes = None if "permanentFailCodes" in _doc: try: permanentFailCodes = load_field( _doc.get("permanentFailCodes"), union_of_None_type_or_array_of_inttype, baseuri, loadingOptions, lc=_doc.get("permanentFailCodes") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `permanentFailCodes`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("permanentFailCodes") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `permanentFailCodes` field is not valid because:", SourceLine(_doc, "permanentFailCodes", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `permanentFailCodes` field is not valid because:", SourceLine(_doc, "permanentFailCodes", str), [e], detailed_message=f"the `permanentFailCodes` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `id`, `label`, `doc`, `inputs`, `outputs`, `requirements`, `hints`, `cwlVersion`, `intent`, `class`, `baseCommand`, `arguments`, `stdin`, `stderr`, `stdout`, `successCodes`, `temporaryFailCodes`, `permanentFailCodes`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( id=id, label=label, doc=doc, inputs=inputs, outputs=outputs, requirements=requirements, hints=hints, cwlVersion=cwlVersion, intent=intent, baseCommand=baseCommand, arguments=arguments, stdin=stdin, stderr=stderr, stdout=stdout, successCodes=successCodes, temporaryFailCodes=temporaryFailCodes, permanentFailCodes=permanentFailCodes, extension_fields=extension_fields, loadingOptions=loadingOptions, ) loadingOptions.idx[cast(str, id)] = (_constructed, loadingOptions) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.id is not None: u = save_relative_uri(self.id, base_url, True, None, relative_uris) r["id"] = u if self.class_ is not None: uri = self.loadingOptions.vocab[self.class_] if p := self.loadingOptions.rvocab.get(uri[: -len(self.class_)]): uri = f"{p}:{self.class_}" else: uri = self.class_ u = save_relative_uri(uri, self.id, False, None, relative_uris) r["class"] = u if self.label is not None: r["label"] = save( self.label, top=False, base_url=self.id, relative_uris=relative_uris ) if self.doc is not None: r["doc"] = save( self.doc, top=False, base_url=self.id, relative_uris=relative_uris ) if self.inputs is not None: r["inputs"] = save( self.inputs, top=False, base_url=self.id, relative_uris=relative_uris ) if self.outputs is not None: r["outputs"] = save( self.outputs, top=False, base_url=self.id, relative_uris=relative_uris ) if self.requirements is not None: r["requirements"] = save( self.requirements, top=False, base_url=self.id, relative_uris=relative_uris, ) if self.hints is not None: r["hints"] = save( self.hints, top=False, base_url=self.id, relative_uris=relative_uris ) if self.cwlVersion is not None: u = save_relative_uri(self.cwlVersion, self.id, False, None, relative_uris) r["cwlVersion"] = u if self.intent is not None: u = save_relative_uri(self.intent, self.id, True, None, relative_uris) r["intent"] = u if self.baseCommand is not None: r["baseCommand"] = save( self.baseCommand, top=False, base_url=self.id, relative_uris=relative_uris, ) if self.arguments is not None: r["arguments"] = save( self.arguments, top=False, base_url=self.id, relative_uris=relative_uris ) if self.stdin is not None: r["stdin"] = save( self.stdin, top=False, base_url=self.id, relative_uris=relative_uris ) if self.stderr is not None: r["stderr"] = save( self.stderr, top=False, base_url=self.id, relative_uris=relative_uris ) if self.stdout is not None: r["stdout"] = save( self.stdout, top=False, base_url=self.id, relative_uris=relative_uris ) if self.successCodes is not None: r["successCodes"] = save( self.successCodes, top=False, base_url=self.id, relative_uris=relative_uris, ) if self.temporaryFailCodes is not None: r["temporaryFailCodes"] = save( self.temporaryFailCodes, top=False, base_url=self.id, relative_uris=relative_uris, ) if self.permanentFailCodes is not None: r["permanentFailCodes"] = save( self.permanentFailCodes, top=False, base_url=self.id, relative_uris=relative_uris, ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset( [ "id", "label", "doc", "inputs", "outputs", "requirements", "hints", "cwlVersion", "intent", "class", "baseCommand", "arguments", "stdin", "stderr", "stdout", "successCodes", "temporaryFailCodes", "permanentFailCodes", ] ) class DockerRequirement(ProcessRequirement): """ Indicates that a workflow component should be run in a [Docker](https://docker.com) or Docker-compatible (such as [Singularity](https://www.sylabs.io/) and [udocker](https://github.com/indigo-dc/udocker)) container environment and specifies how to fetch or build the image. If a CommandLineTool lists `DockerRequirement` under `hints` (or `requirements`), it may (or must) be run in the specified Docker container. The platform must first acquire or install the correct Docker image as specified by `dockerPull`, `dockerImport`, `dockerLoad` or `dockerFile`. The platform must execute the tool in the container using `docker run` with the appropriate Docker image and tool command line. The workflow platform may provide input files and the designated output directory through the use of volume bind mounts. The platform should rewrite file paths in the input object to correspond to the Docker bind mounted locations. That is, the platform should rewrite values in the parameter context such as `runtime.outdir`, `runtime.tmpdir` and others to be valid paths within the container. The platform must ensure that `runtime.outdir` and `runtime.tmpdir` are distinct directories. When running a tool contained in Docker, the workflow platform must not assume anything about the contents of the Docker container, such as the presence or absence of specific software, except to assume that the generated command line represents a valid command within the runtime environment of the container. A container image may specify an [ENTRYPOINT](https://docs.docker.com/engine/reference/builder/#entrypoint) and/or [CMD](https://docs.docker.com/engine/reference/builder/#cmd). Command line arguments will be appended after all elements of ENTRYPOINT, and will override all elements specified using CMD (in other words, CMD is only used when the CommandLineTool definition produces an empty command line). Use of implicit ENTRYPOINT or CMD are discouraged due to reproducibility concerns of the implicit hidden execution point (For further discussion, see [https://doi.org/10.12688/f1000research.15140.1](https://doi.org/10.12688/f1000research.15140.1)). Portable CommandLineTool wrappers in which use of a container is optional must not rely on ENTRYPOINT or CMD. CommandLineTools which do rely on ENTRYPOINT or CMD must list `DockerRequirement` in the `requirements` section. ## Interaction with other requirements If [EnvVarRequirement](#EnvVarRequirement) is specified alongside a DockerRequirement, the environment variables must be provided to Docker using `--env` or `--env-file` and interact with the container's preexisting environment as defined by Docker. """ def __init__( self, dockerPull: Optional[Any] = None, dockerLoad: Optional[Any] = None, dockerFile: Optional[Any] = None, dockerImport: Optional[Any] = None, dockerImageId: Optional[Any] = None, dockerOutputDirectory: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.class_ = "DockerRequirement" self.dockerPull = dockerPull self.dockerLoad = dockerLoad self.dockerFile = dockerFile self.dockerImport = dockerImport self.dockerImageId = dockerImageId self.dockerOutputDirectory = dockerOutputDirectory def __eq__(self, other: Any) -> bool: if isinstance(other, DockerRequirement): return bool( self.class_ == other.class_ and self.dockerPull == other.dockerPull and self.dockerLoad == other.dockerLoad and self.dockerFile == other.dockerFile and self.dockerImport == other.dockerImport and self.dockerImageId == other.dockerImageId and self.dockerOutputDirectory == other.dockerOutputDirectory ) return False def __hash__(self) -> int: return hash( ( self.class_, self.dockerPull, self.dockerLoad, self.dockerFile, self.dockerImport, self.dockerImageId, self.dockerOutputDirectory, ) ) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "DockerRequirement": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("class") is None: raise ValidationException("missing required field `class`", None, []) class_ = load_field( _doc.get("class"), uri_DockerRequirement_classLoader_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("class") ) if class_ not in (cls.__name__, loadingOptions.vocab.get(cls.__name__)): raise ValidationException(f"tried `{cls.__name__}` but") except ValidationException as e: raise e dockerPull = None if "dockerPull" in _doc: try: dockerPull = load_field( _doc.get("dockerPull"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("dockerPull") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `dockerPull`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("dockerPull") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `dockerPull` field is not valid because:", SourceLine(_doc, "dockerPull", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `dockerPull` field is not valid because:", SourceLine(_doc, "dockerPull", str), [e], detailed_message=f"the `dockerPull` field with value `{val}` " "is not valid because:", ) ) dockerLoad = None if "dockerLoad" in _doc: try: dockerLoad = load_field( _doc.get("dockerLoad"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("dockerLoad") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `dockerLoad`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("dockerLoad") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `dockerLoad` field is not valid because:", SourceLine(_doc, "dockerLoad", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `dockerLoad` field is not valid because:", SourceLine(_doc, "dockerLoad", str), [e], detailed_message=f"the `dockerLoad` field with value `{val}` " "is not valid because:", ) ) dockerFile = None if "dockerFile" in _doc: try: dockerFile = load_field( _doc.get("dockerFile"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("dockerFile") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `dockerFile`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("dockerFile") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `dockerFile` field is not valid because:", SourceLine(_doc, "dockerFile", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `dockerFile` field is not valid because:", SourceLine(_doc, "dockerFile", str), [e], detailed_message=f"the `dockerFile` field with value `{val}` " "is not valid because:", ) ) dockerImport = None if "dockerImport" in _doc: try: dockerImport = load_field( _doc.get("dockerImport"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("dockerImport") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `dockerImport`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("dockerImport") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `dockerImport` field is not valid because:", SourceLine(_doc, "dockerImport", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `dockerImport` field is not valid because:", SourceLine(_doc, "dockerImport", str), [e], detailed_message=f"the `dockerImport` field with value `{val}` " "is not valid because:", ) ) dockerImageId = None if "dockerImageId" in _doc: try: dockerImageId = load_field( _doc.get("dockerImageId"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("dockerImageId") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `dockerImageId`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("dockerImageId") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `dockerImageId` field is not valid because:", SourceLine(_doc, "dockerImageId", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `dockerImageId` field is not valid because:", SourceLine(_doc, "dockerImageId", str), [e], detailed_message=f"the `dockerImageId` field with value `{val}` " "is not valid because:", ) ) dockerOutputDirectory = None if "dockerOutputDirectory" in _doc: try: dockerOutputDirectory = load_field( _doc.get("dockerOutputDirectory"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("dockerOutputDirectory") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `dockerOutputDirectory`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("dockerOutputDirectory") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `dockerOutputDirectory` field is not valid because:", SourceLine(_doc, "dockerOutputDirectory", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `dockerOutputDirectory` field is not valid because:", SourceLine(_doc, "dockerOutputDirectory", str), [e], detailed_message=f"the `dockerOutputDirectory` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `class`, `dockerPull`, `dockerLoad`, `dockerFile`, `dockerImport`, `dockerImageId`, `dockerOutputDirectory`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( dockerPull=dockerPull, dockerLoad=dockerLoad, dockerFile=dockerFile, dockerImport=dockerImport, dockerImageId=dockerImageId, dockerOutputDirectory=dockerOutputDirectory, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.class_ is not None: uri = self.loadingOptions.vocab[self.class_] if p := self.loadingOptions.rvocab.get(uri[: -len(self.class_)]): uri = f"{p}:{self.class_}" else: uri = self.class_ u = save_relative_uri(uri, base_url, False, None, relative_uris) r["class"] = u if self.dockerPull is not None: r["dockerPull"] = save( self.dockerPull, top=False, base_url=base_url, relative_uris=relative_uris, ) if self.dockerLoad is not None: r["dockerLoad"] = save( self.dockerLoad, top=False, base_url=base_url, relative_uris=relative_uris, ) if self.dockerFile is not None: r["dockerFile"] = save( self.dockerFile, top=False, base_url=base_url, relative_uris=relative_uris, ) if self.dockerImport is not None: r["dockerImport"] = save( self.dockerImport, top=False, base_url=base_url, relative_uris=relative_uris, ) if self.dockerImageId is not None: r["dockerImageId"] = save( self.dockerImageId, top=False, base_url=base_url, relative_uris=relative_uris, ) if self.dockerOutputDirectory is not None: r["dockerOutputDirectory"] = save( self.dockerOutputDirectory, top=False, base_url=base_url, relative_uris=relative_uris, ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset( [ "class", "dockerPull", "dockerLoad", "dockerFile", "dockerImport", "dockerImageId", "dockerOutputDirectory", ] ) class SoftwareRequirement(ProcessRequirement): """ A list of software packages that should be configured in the environment of the defined process. """ def __init__( self, packages: Any, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.class_ = "SoftwareRequirement" self.packages = packages def __eq__(self, other: Any) -> bool: if isinstance(other, SoftwareRequirement): return bool(self.class_ == other.class_ and self.packages == other.packages) return False def __hash__(self) -> int: return hash((self.class_, self.packages)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "SoftwareRequirement": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("class") is None: raise ValidationException("missing required field `class`", None, []) class_ = load_field( _doc.get("class"), uri_SoftwareRequirement_classLoader_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("class") ) if class_ not in (cls.__name__, loadingOptions.vocab.get(cls.__name__)): raise ValidationException(f"tried `{cls.__name__}` but") except ValidationException as e: raise e try: if _doc.get("packages") is None: raise ValidationException("missing required field `packages`", None, []) packages = load_field( _doc.get("packages"), idmap_packages_array_of_SoftwarePackageLoader, baseuri, loadingOptions, lc=_doc.get("packages") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `packages`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("packages") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `packages` field is not valid because:", SourceLine(_doc, "packages", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `packages` field is not valid because:", SourceLine(_doc, "packages", str), [e], detailed_message=f"the `packages` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `class`, `packages`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( packages=packages, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.class_ is not None: uri = self.loadingOptions.vocab[self.class_] if p := self.loadingOptions.rvocab.get(uri[: -len(self.class_)]): uri = f"{p}:{self.class_}" else: uri = self.class_ u = save_relative_uri(uri, base_url, False, None, relative_uris) r["class"] = u if self.packages is not None: r["packages"] = save( self.packages, top=False, base_url=base_url, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["class", "packages"]) class SoftwarePackage(Saveable): def __init__( self, package: Any, version: Optional[Any] = None, specs: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.package = package self.version = version self.specs = specs def __eq__(self, other: Any) -> bool: if isinstance(other, SoftwarePackage): return bool( self.package == other.package and self.version == other.version and self.specs == other.specs ) return False def __hash__(self) -> int: return hash((self.package, self.version, self.specs)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "SoftwarePackage": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("package") is None: raise ValidationException("missing required field `package`", None, []) package = load_field( _doc.get("package"), strtype, baseuri, loadingOptions, lc=_doc.get("package") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `package`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("package") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `package` field is not valid because:", SourceLine(_doc, "package", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `package` field is not valid because:", SourceLine(_doc, "package", str), [e], detailed_message=f"the `package` field with value `{val}` " "is not valid because:", ) ) version = None if "version" in _doc: try: version = load_field( _doc.get("version"), union_of_None_type_or_array_of_strtype, baseuri, loadingOptions, lc=_doc.get("version") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `version`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("version") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `version` field is not valid because:", SourceLine(_doc, "version", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `version` field is not valid because:", SourceLine(_doc, "version", str), [e], detailed_message=f"the `version` field with value `{val}` " "is not valid because:", ) ) specs = None if "specs" in _doc: try: specs = load_field( _doc.get("specs"), uri_union_of_None_type_or_array_of_strtype_False_False_None_True, baseuri, loadingOptions, lc=_doc.get("specs") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `specs`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("specs") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `specs` field is not valid because:", SourceLine(_doc, "specs", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `specs` field is not valid because:", SourceLine(_doc, "specs", str), [e], detailed_message=f"the `specs` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `package`, `version`, `specs`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( package=package, version=version, specs=specs, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.package is not None: r["package"] = save( self.package, top=False, base_url=base_url, relative_uris=relative_uris ) if self.version is not None: r["version"] = save( self.version, top=False, base_url=base_url, relative_uris=relative_uris ) if self.specs is not None: u = save_relative_uri(self.specs, base_url, False, None, relative_uris) r["specs"] = u # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["package", "version", "specs"]) class Dirent(Saveable): """ Define a file or subdirectory that must be staged to a particular place prior to executing the command line tool. May be the result of executing an expression, such as building a configuration file from a template. Usually files are staged within the [designated output directory](#Runtime_environment). However, under certain circumstances, files may be staged at arbitrary locations, see discussion for `entryname`. """ def __init__( self, entry: Any, entryname: Optional[Any] = None, writable: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.entryname = entryname self.entry = entry self.writable = writable def __eq__(self, other: Any) -> bool: if isinstance(other, Dirent): return bool( self.entryname == other.entryname and self.entry == other.entry and self.writable == other.writable ) return False def __hash__(self) -> int: return hash((self.entryname, self.entry, self.writable)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "Dirent": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] entryname = None if "entryname" in _doc: try: entryname = load_field( _doc.get("entryname"), union_of_None_type_or_strtype_or_ExpressionLoader, baseuri, loadingOptions, lc=_doc.get("entryname") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `entryname`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("entryname") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `entryname` field is not valid because:", SourceLine(_doc, "entryname", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `entryname` field is not valid because:", SourceLine(_doc, "entryname", str), [e], detailed_message=f"the `entryname` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("entry") is None: raise ValidationException("missing required field `entry`", None, []) entry = load_field( _doc.get("entry"), union_of_strtype_or_ExpressionLoader, baseuri, loadingOptions, lc=_doc.get("entry") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `entry`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("entry") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `entry` field is not valid because:", SourceLine(_doc, "entry", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `entry` field is not valid because:", SourceLine(_doc, "entry", str), [e], detailed_message=f"the `entry` field with value `{val}` " "is not valid because:", ) ) writable = None if "writable" in _doc: try: writable = load_field( _doc.get("writable"), union_of_None_type_or_booltype, baseuri, loadingOptions, lc=_doc.get("writable") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `writable`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("writable") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `writable` field is not valid because:", SourceLine(_doc, "writable", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `writable` field is not valid because:", SourceLine(_doc, "writable", str), [e], detailed_message=f"the `writable` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `entryname`, `entry`, `writable`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( entryname=entryname, entry=entry, writable=writable, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.entryname is not None: r["entryname"] = save( self.entryname, top=False, base_url=base_url, relative_uris=relative_uris, ) if self.entry is not None: r["entry"] = save( self.entry, top=False, base_url=base_url, relative_uris=relative_uris ) if self.writable is not None: r["writable"] = save( self.writable, top=False, base_url=base_url, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["entryname", "entry", "writable"]) class InitialWorkDirRequirement(ProcessRequirement): """ Define a list of files and subdirectories that must be staged by the workflow platform prior to executing the command line tool. Normally files are staged within the designated output directory. However, when running inside containers, files may be staged at arbitrary locations, see discussion for [`Dirent.entryname`](#Dirent). Together with `DockerRequirement.dockerOutputDirectory` it is possible to control the locations of both input and output files when running in containers. """ def __init__( self, listing: Any, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.class_ = "InitialWorkDirRequirement" self.listing = listing def __eq__(self, other: Any) -> bool: if isinstance(other, InitialWorkDirRequirement): return bool(self.class_ == other.class_ and self.listing == other.listing) return False def __hash__(self) -> int: return hash((self.class_, self.listing)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "InitialWorkDirRequirement": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("class") is None: raise ValidationException("missing required field `class`", None, []) class_ = load_field( _doc.get("class"), uri_InitialWorkDirRequirement_classLoader_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("class") ) if class_ not in (cls.__name__, loadingOptions.vocab.get(cls.__name__)): raise ValidationException(f"tried `{cls.__name__}` but") except ValidationException as e: raise e try: if _doc.get("listing") is None: raise ValidationException("missing required field `listing`", None, []) listing = load_field( _doc.get("listing"), union_of_ExpressionLoader_or_array_of_union_of_None_type_or_DirentLoader_or_ExpressionLoader_or_FileLoader_or_DirectoryLoader_or_array_of_union_of_FileLoader_or_DirectoryLoader, baseuri, loadingOptions, lc=_doc.get("listing") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `listing`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("listing") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `listing` field is not valid because:", SourceLine(_doc, "listing", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `listing` field is not valid because:", SourceLine(_doc, "listing", str), [e], detailed_message=f"the `listing` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `class`, `listing`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( listing=listing, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.class_ is not None: uri = self.loadingOptions.vocab[self.class_] if p := self.loadingOptions.rvocab.get(uri[: -len(self.class_)]): uri = f"{p}:{self.class_}" else: uri = self.class_ u = save_relative_uri(uri, base_url, False, None, relative_uris) r["class"] = u if self.listing is not None: r["listing"] = save( self.listing, top=False, base_url=base_url, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["class", "listing"]) class EnvVarRequirement(ProcessRequirement): """ Define a list of environment variables which will be set in the execution environment of the tool. See `EnvironmentDef` for details. """ def __init__( self, envDef: Any, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.class_ = "EnvVarRequirement" self.envDef = envDef def __eq__(self, other: Any) -> bool: if isinstance(other, EnvVarRequirement): return bool(self.class_ == other.class_ and self.envDef == other.envDef) return False def __hash__(self) -> int: return hash((self.class_, self.envDef)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "EnvVarRequirement": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("class") is None: raise ValidationException("missing required field `class`", None, []) class_ = load_field( _doc.get("class"), uri_EnvVarRequirement_classLoader_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("class") ) if class_ not in (cls.__name__, loadingOptions.vocab.get(cls.__name__)): raise ValidationException(f"tried `{cls.__name__}` but") except ValidationException as e: raise e try: if _doc.get("envDef") is None: raise ValidationException("missing required field `envDef`", None, []) envDef = load_field( _doc.get("envDef"), idmap_envDef_array_of_EnvironmentDefLoader, baseuri, loadingOptions, lc=_doc.get("envDef") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `envDef`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("envDef") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `envDef` field is not valid because:", SourceLine(_doc, "envDef", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `envDef` field is not valid because:", SourceLine(_doc, "envDef", str), [e], detailed_message=f"the `envDef` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `class`, `envDef`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( envDef=envDef, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.class_ is not None: uri = self.loadingOptions.vocab[self.class_] if p := self.loadingOptions.rvocab.get(uri[: -len(self.class_)]): uri = f"{p}:{self.class_}" else: uri = self.class_ u = save_relative_uri(uri, base_url, False, None, relative_uris) r["class"] = u if self.envDef is not None: r["envDef"] = save( self.envDef, top=False, base_url=base_url, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["class", "envDef"]) class ShellCommandRequirement(ProcessRequirement): """ Modify the behavior of CommandLineTool to generate a single string containing a shell command line. Each item in the `arguments` list must be joined into a string separated by single spaces and quoted to prevent interpretation by the shell, unless `CommandLineBinding` for that argument contains `shellQuote: false`. If `shellQuote: false` is specified, the argument is joined into the command string without quoting, which allows the use of shell metacharacters such as `|` for pipes. """ def __init__( self, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.class_ = "ShellCommandRequirement" def __eq__(self, other: Any) -> bool: if isinstance(other, ShellCommandRequirement): return bool(self.class_ == other.class_) return False def __hash__(self) -> int: return hash((self.class_)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "ShellCommandRequirement": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("class") is None: raise ValidationException("missing required field `class`", None, []) class_ = load_field( _doc.get("class"), uri_ShellCommandRequirement_classLoader_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("class") ) if class_ not in (cls.__name__, loadingOptions.vocab.get(cls.__name__)): raise ValidationException(f"tried `{cls.__name__}` but") except ValidationException as e: raise e extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `class`".format(k), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.class_ is not None: uri = self.loadingOptions.vocab[self.class_] if p := self.loadingOptions.rvocab.get(uri[: -len(self.class_)]): uri = f"{p}:{self.class_}" else: uri = self.class_ u = save_relative_uri(uri, base_url, False, None, relative_uris) r["class"] = u # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["class"]) class ResourceRequirement(ProcessRequirement): """ Specify basic hardware resource requirements. "min" is the minimum amount of a resource that must be reserved to schedule a job. If "min" cannot be satisfied, the job should not be run. "max" is the maximum amount of a resource that the job shall be allocated. If a node has sufficient resources, multiple jobs may be scheduled on a single node provided each job's "max" resource requirements are met. If a job attempts to exceed its resource allocation, an implementation may deny additional resources, which may result in job failure. If both "min" and "max" are specified, an implementation may choose to allocate any amount between "min" and "max", with the actual allocation provided in the `runtime` object. If "min" is specified but "max" is not, then "max" == "min" If "max" is specified by "min" is not, then "min" == "max". It is an error if max < min. It is an error if the value of any of these fields is negative. If neither "min" nor "max" is specified for a resource, use the default values below. """ def __init__( self, coresMin: Optional[Any] = None, coresMax: Optional[Any] = None, ramMin: Optional[Any] = None, ramMax: Optional[Any] = None, tmpdirMin: Optional[Any] = None, tmpdirMax: Optional[Any] = None, outdirMin: Optional[Any] = None, outdirMax: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.class_ = "ResourceRequirement" self.coresMin = coresMin self.coresMax = coresMax self.ramMin = ramMin self.ramMax = ramMax self.tmpdirMin = tmpdirMin self.tmpdirMax = tmpdirMax self.outdirMin = outdirMin self.outdirMax = outdirMax def __eq__(self, other: Any) -> bool: if isinstance(other, ResourceRequirement): return bool( self.class_ == other.class_ and self.coresMin == other.coresMin and self.coresMax == other.coresMax and self.ramMin == other.ramMin and self.ramMax == other.ramMax and self.tmpdirMin == other.tmpdirMin and self.tmpdirMax == other.tmpdirMax and self.outdirMin == other.outdirMin and self.outdirMax == other.outdirMax ) return False def __hash__(self) -> int: return hash( ( self.class_, self.coresMin, self.coresMax, self.ramMin, self.ramMax, self.tmpdirMin, self.tmpdirMax, self.outdirMin, self.outdirMax, ) ) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "ResourceRequirement": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("class") is None: raise ValidationException("missing required field `class`", None, []) class_ = load_field( _doc.get("class"), uri_ResourceRequirement_classLoader_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("class") ) if class_ not in (cls.__name__, loadingOptions.vocab.get(cls.__name__)): raise ValidationException(f"tried `{cls.__name__}` but") except ValidationException as e: raise e coresMin = None if "coresMin" in _doc: try: coresMin = load_field( _doc.get("coresMin"), union_of_None_type_or_inttype_or_floattype_or_ExpressionLoader, baseuri, loadingOptions, lc=_doc.get("coresMin") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `coresMin`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("coresMin") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `coresMin` field is not valid because:", SourceLine(_doc, "coresMin", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `coresMin` field is not valid because:", SourceLine(_doc, "coresMin", str), [e], detailed_message=f"the `coresMin` field with value `{val}` " "is not valid because:", ) ) coresMax = None if "coresMax" in _doc: try: coresMax = load_field( _doc.get("coresMax"), union_of_None_type_or_inttype_or_floattype_or_ExpressionLoader, baseuri, loadingOptions, lc=_doc.get("coresMax") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `coresMax`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("coresMax") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `coresMax` field is not valid because:", SourceLine(_doc, "coresMax", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `coresMax` field is not valid because:", SourceLine(_doc, "coresMax", str), [e], detailed_message=f"the `coresMax` field with value `{val}` " "is not valid because:", ) ) ramMin = None if "ramMin" in _doc: try: ramMin = load_field( _doc.get("ramMin"), union_of_None_type_or_inttype_or_floattype_or_ExpressionLoader, baseuri, loadingOptions, lc=_doc.get("ramMin") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `ramMin`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("ramMin") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `ramMin` field is not valid because:", SourceLine(_doc, "ramMin", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `ramMin` field is not valid because:", SourceLine(_doc, "ramMin", str), [e], detailed_message=f"the `ramMin` field with value `{val}` " "is not valid because:", ) ) ramMax = None if "ramMax" in _doc: try: ramMax = load_field( _doc.get("ramMax"), union_of_None_type_or_inttype_or_floattype_or_ExpressionLoader, baseuri, loadingOptions, lc=_doc.get("ramMax") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `ramMax`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("ramMax") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `ramMax` field is not valid because:", SourceLine(_doc, "ramMax", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `ramMax` field is not valid because:", SourceLine(_doc, "ramMax", str), [e], detailed_message=f"the `ramMax` field with value `{val}` " "is not valid because:", ) ) tmpdirMin = None if "tmpdirMin" in _doc: try: tmpdirMin = load_field( _doc.get("tmpdirMin"), union_of_None_type_or_inttype_or_floattype_or_ExpressionLoader, baseuri, loadingOptions, lc=_doc.get("tmpdirMin") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `tmpdirMin`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("tmpdirMin") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `tmpdirMin` field is not valid because:", SourceLine(_doc, "tmpdirMin", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `tmpdirMin` field is not valid because:", SourceLine(_doc, "tmpdirMin", str), [e], detailed_message=f"the `tmpdirMin` field with value `{val}` " "is not valid because:", ) ) tmpdirMax = None if "tmpdirMax" in _doc: try: tmpdirMax = load_field( _doc.get("tmpdirMax"), union_of_None_type_or_inttype_or_floattype_or_ExpressionLoader, baseuri, loadingOptions, lc=_doc.get("tmpdirMax") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `tmpdirMax`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("tmpdirMax") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `tmpdirMax` field is not valid because:", SourceLine(_doc, "tmpdirMax", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `tmpdirMax` field is not valid because:", SourceLine(_doc, "tmpdirMax", str), [e], detailed_message=f"the `tmpdirMax` field with value `{val}` " "is not valid because:", ) ) outdirMin = None if "outdirMin" in _doc: try: outdirMin = load_field( _doc.get("outdirMin"), union_of_None_type_or_inttype_or_floattype_or_ExpressionLoader, baseuri, loadingOptions, lc=_doc.get("outdirMin") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `outdirMin`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("outdirMin") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `outdirMin` field is not valid because:", SourceLine(_doc, "outdirMin", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `outdirMin` field is not valid because:", SourceLine(_doc, "outdirMin", str), [e], detailed_message=f"the `outdirMin` field with value `{val}` " "is not valid because:", ) ) outdirMax = None if "outdirMax" in _doc: try: outdirMax = load_field( _doc.get("outdirMax"), union_of_None_type_or_inttype_or_floattype_or_ExpressionLoader, baseuri, loadingOptions, lc=_doc.get("outdirMax") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `outdirMax`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("outdirMax") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `outdirMax` field is not valid because:", SourceLine(_doc, "outdirMax", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `outdirMax` field is not valid because:", SourceLine(_doc, "outdirMax", str), [e], detailed_message=f"the `outdirMax` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `class`, `coresMin`, `coresMax`, `ramMin`, `ramMax`, `tmpdirMin`, `tmpdirMax`, `outdirMin`, `outdirMax`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( coresMin=coresMin, coresMax=coresMax, ramMin=ramMin, ramMax=ramMax, tmpdirMin=tmpdirMin, tmpdirMax=tmpdirMax, outdirMin=outdirMin, outdirMax=outdirMax, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.class_ is not None: uri = self.loadingOptions.vocab[self.class_] if p := self.loadingOptions.rvocab.get(uri[: -len(self.class_)]): uri = f"{p}:{self.class_}" else: uri = self.class_ u = save_relative_uri(uri, base_url, False, None, relative_uris) r["class"] = u if self.coresMin is not None: r["coresMin"] = save( self.coresMin, top=False, base_url=base_url, relative_uris=relative_uris ) if self.coresMax is not None: r["coresMax"] = save( self.coresMax, top=False, base_url=base_url, relative_uris=relative_uris ) if self.ramMin is not None: r["ramMin"] = save( self.ramMin, top=False, base_url=base_url, relative_uris=relative_uris ) if self.ramMax is not None: r["ramMax"] = save( self.ramMax, top=False, base_url=base_url, relative_uris=relative_uris ) if self.tmpdirMin is not None: r["tmpdirMin"] = save( self.tmpdirMin, top=False, base_url=base_url, relative_uris=relative_uris, ) if self.tmpdirMax is not None: r["tmpdirMax"] = save( self.tmpdirMax, top=False, base_url=base_url, relative_uris=relative_uris, ) if self.outdirMin is not None: r["outdirMin"] = save( self.outdirMin, top=False, base_url=base_url, relative_uris=relative_uris, ) if self.outdirMax is not None: r["outdirMax"] = save( self.outdirMax, top=False, base_url=base_url, relative_uris=relative_uris, ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset( [ "class", "coresMin", "coresMax", "ramMin", "ramMax", "tmpdirMin", "tmpdirMax", "outdirMin", "outdirMax", ] ) class WorkReuse(ProcessRequirement): """ For implementations that support reusing output from past work (on the assumption that same code and same input produce same results), control whether to enable or disable the reuse behavior for a particular tool or step (to accommodate situations where that assumption is incorrect). A reused step is not executed but instead returns the same output as the original execution. If `WorkReuse` is not specified, correct tools should assume it is enabled by default. """ def __init__( self, enableReuse: Any, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.class_ = "WorkReuse" self.enableReuse = enableReuse def __eq__(self, other: Any) -> bool: if isinstance(other, WorkReuse): return bool( self.class_ == other.class_ and self.enableReuse == other.enableReuse ) return False def __hash__(self) -> int: return hash((self.class_, self.enableReuse)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "WorkReuse": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("class") is None: raise ValidationException("missing required field `class`", None, []) class_ = load_field( _doc.get("class"), uri_WorkReuse_classLoader_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("class") ) if class_ not in (cls.__name__, loadingOptions.vocab.get(cls.__name__)): raise ValidationException(f"tried `{cls.__name__}` but") except ValidationException as e: raise e try: if _doc.get("enableReuse") is None: raise ValidationException("missing required field `enableReuse`", None, []) enableReuse = load_field( _doc.get("enableReuse"), union_of_booltype_or_ExpressionLoader, baseuri, loadingOptions, lc=_doc.get("enableReuse") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `enableReuse`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("enableReuse") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `enableReuse` field is not valid because:", SourceLine(_doc, "enableReuse", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `enableReuse` field is not valid because:", SourceLine(_doc, "enableReuse", str), [e], detailed_message=f"the `enableReuse` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `class`, `enableReuse`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( enableReuse=enableReuse, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.class_ is not None: uri = self.loadingOptions.vocab[self.class_] if p := self.loadingOptions.rvocab.get(uri[: -len(self.class_)]): uri = f"{p}:{self.class_}" else: uri = self.class_ u = save_relative_uri(uri, base_url, False, None, relative_uris) r["class"] = u if self.enableReuse is not None: r["enableReuse"] = save( self.enableReuse, top=False, base_url=base_url, relative_uris=relative_uris, ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["class", "enableReuse"]) class NetworkAccess(ProcessRequirement): """ Indicate whether a process requires outgoing IPv4/IPv6 network access. Choice of IPv4 or IPv6 is implementation and site specific, correct tools must support both. If `networkAccess` is false or not specified, tools must not assume network access, except for localhost (the loopback device). If `networkAccess` is true, the tool must be able to make outgoing connections to network resources. Resources may be on a private subnet or the public Internet. However, implementations and sites may apply their own security policies to restrict what is accessible by the tool. Enabling network access does not imply a publicly routable IP address or the ability to accept inbound connections. """ def __init__( self, networkAccess: Any, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.class_ = "NetworkAccess" self.networkAccess = networkAccess def __eq__(self, other: Any) -> bool: if isinstance(other, NetworkAccess): return bool( self.class_ == other.class_ and self.networkAccess == other.networkAccess ) return False def __hash__(self) -> int: return hash((self.class_, self.networkAccess)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "NetworkAccess": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("class") is None: raise ValidationException("missing required field `class`", None, []) class_ = load_field( _doc.get("class"), uri_NetworkAccess_classLoader_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("class") ) if class_ not in (cls.__name__, loadingOptions.vocab.get(cls.__name__)): raise ValidationException(f"tried `{cls.__name__}` but") except ValidationException as e: raise e try: if _doc.get("networkAccess") is None: raise ValidationException("missing required field `networkAccess`", None, []) networkAccess = load_field( _doc.get("networkAccess"), union_of_booltype_or_ExpressionLoader, baseuri, loadingOptions, lc=_doc.get("networkAccess") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `networkAccess`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("networkAccess") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `networkAccess` field is not valid because:", SourceLine(_doc, "networkAccess", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `networkAccess` field is not valid because:", SourceLine(_doc, "networkAccess", str), [e], detailed_message=f"the `networkAccess` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `class`, `networkAccess`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( networkAccess=networkAccess, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.class_ is not None: uri = self.loadingOptions.vocab[self.class_] if p := self.loadingOptions.rvocab.get(uri[: -len(self.class_)]): uri = f"{p}:{self.class_}" else: uri = self.class_ u = save_relative_uri(uri, base_url, False, None, relative_uris) r["class"] = u if self.networkAccess is not None: r["networkAccess"] = save( self.networkAccess, top=False, base_url=base_url, relative_uris=relative_uris, ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["class", "networkAccess"]) class InplaceUpdateRequirement(ProcessRequirement): """ If `inplaceUpdate` is true, then an implementation supporting this feature may permit tools to directly update files with `writable: true` in InitialWorkDirRequirement. That is, as an optimization, files may be destructively modified in place as opposed to copied and updated. An implementation must ensure that only one workflow step may access a writable file at a time. It is an error if a file which is writable by one workflow step file is accessed (for reading or writing) by any other workflow step running independently. However, a file which has been updated in a previous completed step may be used as input to multiple steps, provided it is read-only in every step. Workflow steps which modify a file must produce the modified file as output. Downstream steps which further process the file must use the output of previous steps, and not refer to a common input (this is necessary for both ordering and correctness). Workflow authors should provide this in the `hints` section. The intent of this feature is that workflows produce the same results whether or not InplaceUpdateRequirement is supported by the implementation, and this feature is primarily available as an optimization for particular environments. Users and implementers should be aware that workflows that destructively modify inputs may not be repeatable or reproducible. In particular, enabling this feature implies that WorkReuse should not be enabled. """ def __init__( self, inplaceUpdate: Any, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.class_ = "InplaceUpdateRequirement" self.inplaceUpdate = inplaceUpdate def __eq__(self, other: Any) -> bool: if isinstance(other, InplaceUpdateRequirement): return bool( self.class_ == other.class_ and self.inplaceUpdate == other.inplaceUpdate ) return False def __hash__(self) -> int: return hash((self.class_, self.inplaceUpdate)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "InplaceUpdateRequirement": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("class") is None: raise ValidationException("missing required field `class`", None, []) class_ = load_field( _doc.get("class"), uri_InplaceUpdateRequirement_classLoader_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("class") ) if class_ not in (cls.__name__, loadingOptions.vocab.get(cls.__name__)): raise ValidationException(f"tried `{cls.__name__}` but") except ValidationException as e: raise e try: if _doc.get("inplaceUpdate") is None: raise ValidationException("missing required field `inplaceUpdate`", None, []) inplaceUpdate = load_field( _doc.get("inplaceUpdate"), booltype, baseuri, loadingOptions, lc=_doc.get("inplaceUpdate") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `inplaceUpdate`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("inplaceUpdate") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `inplaceUpdate` field is not valid because:", SourceLine(_doc, "inplaceUpdate", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `inplaceUpdate` field is not valid because:", SourceLine(_doc, "inplaceUpdate", str), [e], detailed_message=f"the `inplaceUpdate` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `class`, `inplaceUpdate`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( inplaceUpdate=inplaceUpdate, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.class_ is not None: uri = self.loadingOptions.vocab[self.class_] if p := self.loadingOptions.rvocab.get(uri[: -len(self.class_)]): uri = f"{p}:{self.class_}" else: uri = self.class_ u = save_relative_uri(uri, base_url, False, None, relative_uris) r["class"] = u if self.inplaceUpdate is not None: r["inplaceUpdate"] = save( self.inplaceUpdate, top=False, base_url=base_url, relative_uris=relative_uris, ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["class", "inplaceUpdate"]) class ToolTimeLimit(ProcessRequirement): """ Set an upper limit on the execution time of a CommandLineTool. A CommandLineTool whose execution duration exceeds the time limit may be preemptively terminated and considered failed. May also be used by batch systems to make scheduling decisions. The execution duration excludes external operations, such as staging of files, pulling a docker image etc, and only counts wall-time for the execution of the command line itself. """ def __init__( self, timelimit: Any, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.class_ = "ToolTimeLimit" self.timelimit = timelimit def __eq__(self, other: Any) -> bool: if isinstance(other, ToolTimeLimit): return bool( self.class_ == other.class_ and self.timelimit == other.timelimit ) return False def __hash__(self) -> int: return hash((self.class_, self.timelimit)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "ToolTimeLimit": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("class") is None: raise ValidationException("missing required field `class`", None, []) class_ = load_field( _doc.get("class"), uri_ToolTimeLimit_classLoader_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("class") ) if class_ not in (cls.__name__, loadingOptions.vocab.get(cls.__name__)): raise ValidationException(f"tried `{cls.__name__}` but") except ValidationException as e: raise e try: if _doc.get("timelimit") is None: raise ValidationException("missing required field `timelimit`", None, []) timelimit = load_field( _doc.get("timelimit"), union_of_inttype_or_ExpressionLoader, baseuri, loadingOptions, lc=_doc.get("timelimit") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `timelimit`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("timelimit") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `timelimit` field is not valid because:", SourceLine(_doc, "timelimit", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `timelimit` field is not valid because:", SourceLine(_doc, "timelimit", str), [e], detailed_message=f"the `timelimit` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `class`, `timelimit`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( timelimit=timelimit, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.class_ is not None: uri = self.loadingOptions.vocab[self.class_] if p := self.loadingOptions.rvocab.get(uri[: -len(self.class_)]): uri = f"{p}:{self.class_}" else: uri = self.class_ u = save_relative_uri(uri, base_url, False, None, relative_uris) r["class"] = u if self.timelimit is not None: r["timelimit"] = save( self.timelimit, top=False, base_url=base_url, relative_uris=relative_uris, ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["class", "timelimit"]) class ExpressionToolOutputParameter(OutputParameter): id: str def __init__( self, id: Any, type_: Any, label: Optional[Any] = None, secondaryFiles: Optional[Any] = None, streamable: Optional[Any] = None, doc: Optional[Any] = None, format: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.label = label self.secondaryFiles = secondaryFiles self.streamable = streamable self.doc = doc self.id = id if id is not None else "_:" + str(_uuid__.uuid4()) self.format = format self.type_ = type_ def __eq__(self, other: Any) -> bool: if isinstance(other, ExpressionToolOutputParameter): return bool( self.label == other.label and self.secondaryFiles == other.secondaryFiles and self.streamable == other.streamable and self.doc == other.doc and self.id == other.id and self.format == other.format and self.type_ == other.type_ ) return False def __hash__(self) -> int: return hash( ( self.label, self.secondaryFiles, self.streamable, self.doc, self.id, self.format, self.type_, ) ) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "ExpressionToolOutputParameter": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] id = None if "id" in _doc: try: id = load_field( _doc.get("id"), uri_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("id") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `id`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("id") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `id` field is not valid because:", SourceLine(_doc, "id", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `id` field is not valid because:", SourceLine(_doc, "id", str), [e], detailed_message=f"the `id` field with value `{val}` " "is not valid because:", ) ) __original_id_is_none = id is None if id is None: if docRoot is not None: id = docRoot else: _errors__.append(ValidationException("missing id")) if not __original_id_is_none: baseuri = cast(str, id) label = None if "label" in _doc: try: label = load_field( _doc.get("label"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("label") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `label`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("label") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [e], detailed_message=f"the `label` field with value `{val}` " "is not valid because:", ) ) secondaryFiles = None if "secondaryFiles" in _doc: try: secondaryFiles = load_field( _doc.get("secondaryFiles"), secondaryfilesdsl_union_of_None_type_or_SecondaryFileSchemaLoader_or_array_of_SecondaryFileSchemaLoader, baseuri, loadingOptions, lc=_doc.get("secondaryFiles") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `secondaryFiles`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("secondaryFiles") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `secondaryFiles` field is not valid because:", SourceLine(_doc, "secondaryFiles", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `secondaryFiles` field is not valid because:", SourceLine(_doc, "secondaryFiles", str), [e], detailed_message=f"the `secondaryFiles` field with value `{val}` " "is not valid because:", ) ) streamable = None if "streamable" in _doc: try: streamable = load_field( _doc.get("streamable"), union_of_None_type_or_booltype, baseuri, loadingOptions, lc=_doc.get("streamable") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `streamable`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("streamable") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `streamable` field is not valid because:", SourceLine(_doc, "streamable", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `streamable` field is not valid because:", SourceLine(_doc, "streamable", str), [e], detailed_message=f"the `streamable` field with value `{val}` " "is not valid because:", ) ) doc = None if "doc" in _doc: try: doc = load_field( _doc.get("doc"), union_of_None_type_or_strtype_or_array_of_strtype, baseuri, loadingOptions, lc=_doc.get("doc") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `doc`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("doc") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [e], detailed_message=f"the `doc` field with value `{val}` " "is not valid because:", ) ) format = None if "format" in _doc: try: format = load_field( _doc.get("format"), uri_union_of_None_type_or_strtype_or_ExpressionLoader_True_False_None_True, baseuri, loadingOptions, lc=_doc.get("format") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `format`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("format") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `format` field is not valid because:", SourceLine(_doc, "format", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `format` field is not valid because:", SourceLine(_doc, "format", str), [e], detailed_message=f"the `format` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("type") is None: raise ValidationException("missing required field `type`", None, []) type_ = load_field( _doc.get("type"), typedsl_union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype_2, baseuri, loadingOptions, lc=_doc.get("type") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `type`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("type") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [e], detailed_message=f"the `type` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `label`, `secondaryFiles`, `streamable`, `doc`, `id`, `format`, `type`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( label=label, secondaryFiles=secondaryFiles, streamable=streamable, doc=doc, id=id, format=format, type_=type_, extension_fields=extension_fields, loadingOptions=loadingOptions, ) loadingOptions.idx[cast(str, id)] = (_constructed, loadingOptions) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.id is not None: u = save_relative_uri(self.id, base_url, True, None, relative_uris) r["id"] = u if self.label is not None: r["label"] = save( self.label, top=False, base_url=self.id, relative_uris=relative_uris ) if self.secondaryFiles is not None: r["secondaryFiles"] = save( self.secondaryFiles, top=False, base_url=self.id, relative_uris=relative_uris, ) if self.streamable is not None: r["streamable"] = save( self.streamable, top=False, base_url=self.id, relative_uris=relative_uris, ) if self.doc is not None: r["doc"] = save( self.doc, top=False, base_url=self.id, relative_uris=relative_uris ) if self.format is not None: u = save_relative_uri(self.format, self.id, True, None, relative_uris) r["format"] = u if self.type_ is not None: r["type"] = save( self.type_, top=False, base_url=self.id, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset( ["label", "secondaryFiles", "streamable", "doc", "id", "format", "type"] ) class WorkflowInputParameter(InputParameter): id: str def __init__( self, id: Any, type_: Any, label: Optional[Any] = None, secondaryFiles: Optional[Any] = None, streamable: Optional[Any] = None, doc: Optional[Any] = None, format: Optional[Any] = None, loadContents: Optional[Any] = None, loadListing: Optional[Any] = None, default: Optional[Any] = None, inputBinding: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.label = label self.secondaryFiles = secondaryFiles self.streamable = streamable self.doc = doc self.id = id if id is not None else "_:" + str(_uuid__.uuid4()) self.format = format self.loadContents = loadContents self.loadListing = loadListing self.default = default self.type_ = type_ self.inputBinding = inputBinding def __eq__(self, other: Any) -> bool: if isinstance(other, WorkflowInputParameter): return bool( self.label == other.label and self.secondaryFiles == other.secondaryFiles and self.streamable == other.streamable and self.doc == other.doc and self.id == other.id and self.format == other.format and self.loadContents == other.loadContents and self.loadListing == other.loadListing and self.default == other.default and self.type_ == other.type_ and self.inputBinding == other.inputBinding ) return False def __hash__(self) -> int: return hash( ( self.label, self.secondaryFiles, self.streamable, self.doc, self.id, self.format, self.loadContents, self.loadListing, self.default, self.type_, self.inputBinding, ) ) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "WorkflowInputParameter": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] id = None if "id" in _doc: try: id = load_field( _doc.get("id"), uri_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("id") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `id`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("id") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `id` field is not valid because:", SourceLine(_doc, "id", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `id` field is not valid because:", SourceLine(_doc, "id", str), [e], detailed_message=f"the `id` field with value `{val}` " "is not valid because:", ) ) __original_id_is_none = id is None if id is None: if docRoot is not None: id = docRoot else: _errors__.append(ValidationException("missing id")) if not __original_id_is_none: baseuri = cast(str, id) label = None if "label" in _doc: try: label = load_field( _doc.get("label"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("label") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `label`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("label") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [e], detailed_message=f"the `label` field with value `{val}` " "is not valid because:", ) ) secondaryFiles = None if "secondaryFiles" in _doc: try: secondaryFiles = load_field( _doc.get("secondaryFiles"), secondaryfilesdsl_union_of_None_type_or_SecondaryFileSchemaLoader_or_array_of_SecondaryFileSchemaLoader, baseuri, loadingOptions, lc=_doc.get("secondaryFiles") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `secondaryFiles`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("secondaryFiles") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `secondaryFiles` field is not valid because:", SourceLine(_doc, "secondaryFiles", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `secondaryFiles` field is not valid because:", SourceLine(_doc, "secondaryFiles", str), [e], detailed_message=f"the `secondaryFiles` field with value `{val}` " "is not valid because:", ) ) streamable = None if "streamable" in _doc: try: streamable = load_field( _doc.get("streamable"), union_of_None_type_or_booltype, baseuri, loadingOptions, lc=_doc.get("streamable") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `streamable`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("streamable") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `streamable` field is not valid because:", SourceLine(_doc, "streamable", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `streamable` field is not valid because:", SourceLine(_doc, "streamable", str), [e], detailed_message=f"the `streamable` field with value `{val}` " "is not valid because:", ) ) doc = None if "doc" in _doc: try: doc = load_field( _doc.get("doc"), union_of_None_type_or_strtype_or_array_of_strtype, baseuri, loadingOptions, lc=_doc.get("doc") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `doc`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("doc") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [e], detailed_message=f"the `doc` field with value `{val}` " "is not valid because:", ) ) format = None if "format" in _doc: try: format = load_field( _doc.get("format"), uri_union_of_None_type_or_strtype_or_array_of_strtype_or_ExpressionLoader_True_False_None_True, baseuri, loadingOptions, lc=_doc.get("format") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `format`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("format") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `format` field is not valid because:", SourceLine(_doc, "format", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `format` field is not valid because:", SourceLine(_doc, "format", str), [e], detailed_message=f"the `format` field with value `{val}` " "is not valid because:", ) ) loadContents = None if "loadContents" in _doc: try: loadContents = load_field( _doc.get("loadContents"), union_of_None_type_or_booltype, baseuri, loadingOptions, lc=_doc.get("loadContents") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `loadContents`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("loadContents") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `loadContents` field is not valid because:", SourceLine(_doc, "loadContents", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `loadContents` field is not valid because:", SourceLine(_doc, "loadContents", str), [e], detailed_message=f"the `loadContents` field with value `{val}` " "is not valid because:", ) ) loadListing = None if "loadListing" in _doc: try: loadListing = load_field( _doc.get("loadListing"), union_of_None_type_or_LoadListingEnumLoader, baseuri, loadingOptions, lc=_doc.get("loadListing") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `loadListing`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("loadListing") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `loadListing` field is not valid because:", SourceLine(_doc, "loadListing", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `loadListing` field is not valid because:", SourceLine(_doc, "loadListing", str), [e], detailed_message=f"the `loadListing` field with value `{val}` " "is not valid because:", ) ) default = None if "default" in _doc: try: default = load_field( _doc.get("default"), union_of_None_type_or_CWLObjectTypeLoader, baseuri, loadingOptions, lc=_doc.get("default") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `default`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("default") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `default` field is not valid because:", SourceLine(_doc, "default", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `default` field is not valid because:", SourceLine(_doc, "default", str), [e], detailed_message=f"the `default` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("type") is None: raise ValidationException("missing required field `type`", None, []) type_ = load_field( _doc.get("type"), typedsl_union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype_2, baseuri, loadingOptions, lc=_doc.get("type") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `type`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("type") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [e], detailed_message=f"the `type` field with value `{val}` " "is not valid because:", ) ) inputBinding = None if "inputBinding" in _doc: try: inputBinding = load_field( _doc.get("inputBinding"), union_of_None_type_or_InputBindingLoader, baseuri, loadingOptions, lc=_doc.get("inputBinding") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `inputBinding`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("inputBinding") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `inputBinding` field is not valid because:", SourceLine(_doc, "inputBinding", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `inputBinding` field is not valid because:", SourceLine(_doc, "inputBinding", str), [e], detailed_message=f"the `inputBinding` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `label`, `secondaryFiles`, `streamable`, `doc`, `id`, `format`, `loadContents`, `loadListing`, `default`, `type`, `inputBinding`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( label=label, secondaryFiles=secondaryFiles, streamable=streamable, doc=doc, id=id, format=format, loadContents=loadContents, loadListing=loadListing, default=default, type_=type_, inputBinding=inputBinding, extension_fields=extension_fields, loadingOptions=loadingOptions, ) loadingOptions.idx[cast(str, id)] = (_constructed, loadingOptions) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.id is not None: u = save_relative_uri(self.id, base_url, True, None, relative_uris) r["id"] = u if self.label is not None: r["label"] = save( self.label, top=False, base_url=self.id, relative_uris=relative_uris ) if self.secondaryFiles is not None: r["secondaryFiles"] = save( self.secondaryFiles, top=False, base_url=self.id, relative_uris=relative_uris, ) if self.streamable is not None: r["streamable"] = save( self.streamable, top=False, base_url=self.id, relative_uris=relative_uris, ) if self.doc is not None: r["doc"] = save( self.doc, top=False, base_url=self.id, relative_uris=relative_uris ) if self.format is not None: u = save_relative_uri(self.format, self.id, True, None, relative_uris) r["format"] = u if self.loadContents is not None: r["loadContents"] = save( self.loadContents, top=False, base_url=self.id, relative_uris=relative_uris, ) if self.loadListing is not None: r["loadListing"] = save( self.loadListing, top=False, base_url=self.id, relative_uris=relative_uris, ) if self.default is not None: r["default"] = save( self.default, top=False, base_url=self.id, relative_uris=relative_uris ) if self.type_ is not None: r["type"] = save( self.type_, top=False, base_url=self.id, relative_uris=relative_uris ) if self.inputBinding is not None: r["inputBinding"] = save( self.inputBinding, top=False, base_url=self.id, relative_uris=relative_uris, ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset( [ "label", "secondaryFiles", "streamable", "doc", "id", "format", "loadContents", "loadListing", "default", "type", "inputBinding", ] ) class ExpressionTool(Process): """ An ExpressionTool is a type of Process object that can be run by itself or as a Workflow step. It executes a pure Javascript expression that has access to the same input parameters as a workflow. It is meant to be used sparingly as a way to isolate complex Javascript expressions that need to operate on input data and produce some result; perhaps just a rearrangement of the inputs. No Docker software container is required or allowed. """ id: str def __init__( self, inputs: Any, outputs: Any, expression: Any, id: Optional[Any] = None, label: Optional[Any] = None, doc: Optional[Any] = None, requirements: Optional[Any] = None, hints: Optional[Any] = None, cwlVersion: Optional[Any] = None, intent: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.id = id if id is not None else "_:" + str(_uuid__.uuid4()) self.label = label self.doc = doc self.inputs = inputs self.outputs = outputs self.requirements = requirements self.hints = hints self.cwlVersion = cwlVersion self.intent = intent self.class_ = "ExpressionTool" self.expression = expression def __eq__(self, other: Any) -> bool: if isinstance(other, ExpressionTool): return bool( self.id == other.id and self.label == other.label and self.doc == other.doc and self.inputs == other.inputs and self.outputs == other.outputs and self.requirements == other.requirements and self.hints == other.hints and self.cwlVersion == other.cwlVersion and self.intent == other.intent and self.class_ == other.class_ and self.expression == other.expression ) return False def __hash__(self) -> int: return hash( ( self.id, self.label, self.doc, self.inputs, self.outputs, self.requirements, self.hints, self.cwlVersion, self.intent, self.class_, self.expression, ) ) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "ExpressionTool": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] id = None if "id" in _doc: try: id = load_field( _doc.get("id"), uri_union_of_None_type_or_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("id") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `id`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("id") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `id` field is not valid because:", SourceLine(_doc, "id", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `id` field is not valid because:", SourceLine(_doc, "id", str), [e], detailed_message=f"the `id` field with value `{val}` " "is not valid because:", ) ) __original_id_is_none = id is None if id is None: if docRoot is not None: id = docRoot else: id = "_:" + str(_uuid__.uuid4()) if not __original_id_is_none: baseuri = cast(str, id) try: if _doc.get("class") is None: raise ValidationException("missing required field `class`", None, []) class_ = load_field( _doc.get("class"), uri_ExpressionTool_classLoader_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("class") ) if class_ not in (cls.__name__, loadingOptions.vocab.get(cls.__name__)): raise ValidationException(f"tried `{cls.__name__}` but") except ValidationException as e: raise e label = None if "label" in _doc: try: label = load_field( _doc.get("label"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("label") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `label`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("label") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [e], detailed_message=f"the `label` field with value `{val}` " "is not valid because:", ) ) doc = None if "doc" in _doc: try: doc = load_field( _doc.get("doc"), union_of_None_type_or_strtype_or_array_of_strtype, baseuri, loadingOptions, lc=_doc.get("doc") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `doc`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("doc") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [e], detailed_message=f"the `doc` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("inputs") is None: raise ValidationException("missing required field `inputs`", None, []) inputs = load_field( _doc.get("inputs"), idmap_inputs_array_of_WorkflowInputParameterLoader, baseuri, loadingOptions, lc=_doc.get("inputs") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `inputs`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("inputs") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `inputs` field is not valid because:", SourceLine(_doc, "inputs", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `inputs` field is not valid because:", SourceLine(_doc, "inputs", str), [e], detailed_message=f"the `inputs` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("outputs") is None: raise ValidationException("missing required field `outputs`", None, []) outputs = load_field( _doc.get("outputs"), idmap_outputs_array_of_ExpressionToolOutputParameterLoader, baseuri, loadingOptions, lc=_doc.get("outputs") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `outputs`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("outputs") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `outputs` field is not valid because:", SourceLine(_doc, "outputs", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `outputs` field is not valid because:", SourceLine(_doc, "outputs", str), [e], detailed_message=f"the `outputs` field with value `{val}` " "is not valid because:", ) ) requirements = None if "requirements" in _doc: try: requirements = load_field( _doc.get("requirements"), idmap_requirements_union_of_None_type_or_array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_LoadListingRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_WorkReuseLoader_or_NetworkAccessLoader_or_InplaceUpdateRequirementLoader_or_ToolTimeLimitLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader_or_SecretsLoader_or_MPIRequirementLoader_or_CUDARequirementLoader_or_LoopLoader_or_ShmSizeLoader, baseuri, loadingOptions, lc=_doc.get("requirements") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `requirements`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("requirements") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `requirements` field is not valid because:", SourceLine(_doc, "requirements", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `requirements` field is not valid because:", SourceLine(_doc, "requirements", str), [e], detailed_message=f"the `requirements` field with value `{val}` " "is not valid because:", ) ) hints = None if "hints" in _doc: try: hints = load_field( _doc.get("hints"), idmap_hints_union_of_None_type_or_array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_LoadListingRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_WorkReuseLoader_or_NetworkAccessLoader_or_InplaceUpdateRequirementLoader_or_ToolTimeLimitLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader_or_SecretsLoader_or_MPIRequirementLoader_or_CUDARequirementLoader_or_LoopLoader_or_ShmSizeLoader_or_Any_type, baseuri, loadingOptions, lc=_doc.get("hints") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `hints`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("hints") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `hints` field is not valid because:", SourceLine(_doc, "hints", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `hints` field is not valid because:", SourceLine(_doc, "hints", str), [e], detailed_message=f"the `hints` field with value `{val}` " "is not valid because:", ) ) cwlVersion = None if "cwlVersion" in _doc: try: cwlVersion = load_field( _doc.get("cwlVersion"), uri_union_of_None_type_or_CWLVersionLoader_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("cwlVersion") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `cwlVersion`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("cwlVersion") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `cwlVersion` field is not valid because:", SourceLine(_doc, "cwlVersion", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `cwlVersion` field is not valid because:", SourceLine(_doc, "cwlVersion", str), [e], detailed_message=f"the `cwlVersion` field with value `{val}` " "is not valid because:", ) ) intent = None if "intent" in _doc: try: intent = load_field( _doc.get("intent"), uri_union_of_None_type_or_array_of_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("intent") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `intent`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("intent") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `intent` field is not valid because:", SourceLine(_doc, "intent", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `intent` field is not valid because:", SourceLine(_doc, "intent", str), [e], detailed_message=f"the `intent` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("expression") is None: raise ValidationException("missing required field `expression`", None, []) expression = load_field( _doc.get("expression"), ExpressionLoader, baseuri, loadingOptions, lc=_doc.get("expression") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `expression`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("expression") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `expression` field is not valid because:", SourceLine(_doc, "expression", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `expression` field is not valid because:", SourceLine(_doc, "expression", str), [e], detailed_message=f"the `expression` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `id`, `label`, `doc`, `inputs`, `outputs`, `requirements`, `hints`, `cwlVersion`, `intent`, `class`, `expression`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( id=id, label=label, doc=doc, inputs=inputs, outputs=outputs, requirements=requirements, hints=hints, cwlVersion=cwlVersion, intent=intent, expression=expression, extension_fields=extension_fields, loadingOptions=loadingOptions, ) loadingOptions.idx[cast(str, id)] = (_constructed, loadingOptions) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.id is not None: u = save_relative_uri(self.id, base_url, True, None, relative_uris) r["id"] = u if self.class_ is not None: uri = self.loadingOptions.vocab[self.class_] if p := self.loadingOptions.rvocab.get(uri[: -len(self.class_)]): uri = f"{p}:{self.class_}" else: uri = self.class_ u = save_relative_uri(uri, self.id, False, None, relative_uris) r["class"] = u if self.label is not None: r["label"] = save( self.label, top=False, base_url=self.id, relative_uris=relative_uris ) if self.doc is not None: r["doc"] = save( self.doc, top=False, base_url=self.id, relative_uris=relative_uris ) if self.inputs is not None: r["inputs"] = save( self.inputs, top=False, base_url=self.id, relative_uris=relative_uris ) if self.outputs is not None: r["outputs"] = save( self.outputs, top=False, base_url=self.id, relative_uris=relative_uris ) if self.requirements is not None: r["requirements"] = save( self.requirements, top=False, base_url=self.id, relative_uris=relative_uris, ) if self.hints is not None: r["hints"] = save( self.hints, top=False, base_url=self.id, relative_uris=relative_uris ) if self.cwlVersion is not None: u = save_relative_uri(self.cwlVersion, self.id, False, None, relative_uris) r["cwlVersion"] = u if self.intent is not None: u = save_relative_uri(self.intent, self.id, True, None, relative_uris) r["intent"] = u if self.expression is not None: r["expression"] = save( self.expression, top=False, base_url=self.id, relative_uris=relative_uris, ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset( [ "id", "label", "doc", "inputs", "outputs", "requirements", "hints", "cwlVersion", "intent", "class", "expression", ] ) class WorkflowOutputParameter(OutputParameter): """ Describe an output parameter of a workflow. The parameter must be connected to one or more parameters defined in the workflow that will provide the value of the output parameter. It is legal to connect a WorkflowInputParameter to a WorkflowOutputParameter. See [WorkflowStepInput](#WorkflowStepInput) for discussion of `linkMerge` and `pickValue`. """ id: str def __init__( self, id: Any, type_: Any, label: Optional[Any] = None, secondaryFiles: Optional[Any] = None, streamable: Optional[Any] = None, doc: Optional[Any] = None, format: Optional[Any] = None, outputSource: Optional[Any] = None, linkMerge: Optional[Any] = None, pickValue: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.label = label self.secondaryFiles = secondaryFiles self.streamable = streamable self.doc = doc self.id = id if id is not None else "_:" + str(_uuid__.uuid4()) self.format = format self.outputSource = outputSource self.linkMerge = linkMerge self.pickValue = pickValue self.type_ = type_ def __eq__(self, other: Any) -> bool: if isinstance(other, WorkflowOutputParameter): return bool( self.label == other.label and self.secondaryFiles == other.secondaryFiles and self.streamable == other.streamable and self.doc == other.doc and self.id == other.id and self.format == other.format and self.outputSource == other.outputSource and self.linkMerge == other.linkMerge and self.pickValue == other.pickValue and self.type_ == other.type_ ) return False def __hash__(self) -> int: return hash( ( self.label, self.secondaryFiles, self.streamable, self.doc, self.id, self.format, self.outputSource, self.linkMerge, self.pickValue, self.type_, ) ) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "WorkflowOutputParameter": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] id = None if "id" in _doc: try: id = load_field( _doc.get("id"), uri_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("id") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `id`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("id") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `id` field is not valid because:", SourceLine(_doc, "id", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `id` field is not valid because:", SourceLine(_doc, "id", str), [e], detailed_message=f"the `id` field with value `{val}` " "is not valid because:", ) ) __original_id_is_none = id is None if id is None: if docRoot is not None: id = docRoot else: _errors__.append(ValidationException("missing id")) if not __original_id_is_none: baseuri = cast(str, id) label = None if "label" in _doc: try: label = load_field( _doc.get("label"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("label") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `label`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("label") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [e], detailed_message=f"the `label` field with value `{val}` " "is not valid because:", ) ) secondaryFiles = None if "secondaryFiles" in _doc: try: secondaryFiles = load_field( _doc.get("secondaryFiles"), secondaryfilesdsl_union_of_None_type_or_SecondaryFileSchemaLoader_or_array_of_SecondaryFileSchemaLoader, baseuri, loadingOptions, lc=_doc.get("secondaryFiles") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `secondaryFiles`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("secondaryFiles") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `secondaryFiles` field is not valid because:", SourceLine(_doc, "secondaryFiles", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `secondaryFiles` field is not valid because:", SourceLine(_doc, "secondaryFiles", str), [e], detailed_message=f"the `secondaryFiles` field with value `{val}` " "is not valid because:", ) ) streamable = None if "streamable" in _doc: try: streamable = load_field( _doc.get("streamable"), union_of_None_type_or_booltype, baseuri, loadingOptions, lc=_doc.get("streamable") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `streamable`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("streamable") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `streamable` field is not valid because:", SourceLine(_doc, "streamable", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `streamable` field is not valid because:", SourceLine(_doc, "streamable", str), [e], detailed_message=f"the `streamable` field with value `{val}` " "is not valid because:", ) ) doc = None if "doc" in _doc: try: doc = load_field( _doc.get("doc"), union_of_None_type_or_strtype_or_array_of_strtype, baseuri, loadingOptions, lc=_doc.get("doc") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `doc`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("doc") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [e], detailed_message=f"the `doc` field with value `{val}` " "is not valid because:", ) ) format = None if "format" in _doc: try: format = load_field( _doc.get("format"), uri_union_of_None_type_or_strtype_or_ExpressionLoader_True_False_None_True, baseuri, loadingOptions, lc=_doc.get("format") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `format`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("format") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `format` field is not valid because:", SourceLine(_doc, "format", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `format` field is not valid because:", SourceLine(_doc, "format", str), [e], detailed_message=f"the `format` field with value `{val}` " "is not valid because:", ) ) outputSource = None if "outputSource" in _doc: try: outputSource = load_field( _doc.get("outputSource"), uri_union_of_None_type_or_strtype_or_array_of_strtype_False_False_1_None, baseuri, loadingOptions, lc=_doc.get("outputSource") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `outputSource`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("outputSource") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `outputSource` field is not valid because:", SourceLine(_doc, "outputSource", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `outputSource` field is not valid because:", SourceLine(_doc, "outputSource", str), [e], detailed_message=f"the `outputSource` field with value `{val}` " "is not valid because:", ) ) linkMerge = None if "linkMerge" in _doc: try: linkMerge = load_field( _doc.get("linkMerge"), union_of_None_type_or_LinkMergeMethodLoader, baseuri, loadingOptions, lc=_doc.get("linkMerge") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `linkMerge`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("linkMerge") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `linkMerge` field is not valid because:", SourceLine(_doc, "linkMerge", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `linkMerge` field is not valid because:", SourceLine(_doc, "linkMerge", str), [e], detailed_message=f"the `linkMerge` field with value `{val}` " "is not valid because:", ) ) pickValue = None if "pickValue" in _doc: try: pickValue = load_field( _doc.get("pickValue"), union_of_None_type_or_PickValueMethodLoader, baseuri, loadingOptions, lc=_doc.get("pickValue") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `pickValue`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("pickValue") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `pickValue` field is not valid because:", SourceLine(_doc, "pickValue", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `pickValue` field is not valid because:", SourceLine(_doc, "pickValue", str), [e], detailed_message=f"the `pickValue` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("type") is None: raise ValidationException("missing required field `type`", None, []) type_ = load_field( _doc.get("type"), typedsl_union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype_2, baseuri, loadingOptions, lc=_doc.get("type") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `type`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("type") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [e], detailed_message=f"the `type` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `label`, `secondaryFiles`, `streamable`, `doc`, `id`, `format`, `outputSource`, `linkMerge`, `pickValue`, `type`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( label=label, secondaryFiles=secondaryFiles, streamable=streamable, doc=doc, id=id, format=format, outputSource=outputSource, linkMerge=linkMerge, pickValue=pickValue, type_=type_, extension_fields=extension_fields, loadingOptions=loadingOptions, ) loadingOptions.idx[cast(str, id)] = (_constructed, loadingOptions) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.id is not None: u = save_relative_uri(self.id, base_url, True, None, relative_uris) r["id"] = u if self.label is not None: r["label"] = save( self.label, top=False, base_url=self.id, relative_uris=relative_uris ) if self.secondaryFiles is not None: r["secondaryFiles"] = save( self.secondaryFiles, top=False, base_url=self.id, relative_uris=relative_uris, ) if self.streamable is not None: r["streamable"] = save( self.streamable, top=False, base_url=self.id, relative_uris=relative_uris, ) if self.doc is not None: r["doc"] = save( self.doc, top=False, base_url=self.id, relative_uris=relative_uris ) if self.format is not None: u = save_relative_uri(self.format, self.id, True, None, relative_uris) r["format"] = u if self.outputSource is not None: u = save_relative_uri(self.outputSource, self.id, False, 1, relative_uris) r["outputSource"] = u if self.linkMerge is not None: r["linkMerge"] = save( self.linkMerge, top=False, base_url=self.id, relative_uris=relative_uris ) if self.pickValue is not None: r["pickValue"] = save( self.pickValue, top=False, base_url=self.id, relative_uris=relative_uris ) if self.type_ is not None: r["type"] = save( self.type_, top=False, base_url=self.id, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset( [ "label", "secondaryFiles", "streamable", "doc", "id", "format", "outputSource", "linkMerge", "pickValue", "type", ] ) class Sink(Saveable): pass class WorkflowStepInput(IdentifierRequired, Sink, LoadContents, Labeled): """ The input of a workflow step connects an upstream parameter (from the workflow inputs, or the outputs of other workflows steps) with the input parameters of the process specified by the `run` field. Only input parameters declared by the target process will be passed through at runtime to the process though additional parameters may be specified (for use within `valueFrom` expressions for instance) - unconnected or unused parameters do not represent an error condition. # Input object A WorkflowStepInput object must contain an `id` field in the form `#fieldname` or `#prefix/fieldname`. When the `id` field contains a slash `/` the field name consists of the characters following the final slash (the prefix portion may contain one or more slashes to indicate scope). This defines a field of the workflow step input object with the value of the `source` parameter(s). # Merging multiple inbound data links To merge multiple inbound data links, [MultipleInputFeatureRequirement](#MultipleInputFeatureRequirement) must be specified in the workflow or workflow step requirements. If the sink parameter is an array, or named in a [workflow scatter](#WorkflowStep) operation, there may be multiple inbound data links listed in the `source` field. The values from the input links are merged depending on the method specified in the `linkMerge` field. If both `linkMerge` and `pickValue` are null or not specified, and there is more than one element in the `source` array, the default method is "merge_nested". If both `linkMerge` and `pickValue` are null or not specified, and there is only a single element in the `source`, then the input parameter takes the scalar value from the single input link (it is *not* wrapped in a single-list). * **merge_nested** The input must be an array consisting of exactly one entry for each input link. If "merge_nested" is specified with a single link, the value from the link must be wrapped in a single-item list. * **merge_flattened** 1. The source and sink parameters must be compatible types, or the source type must be compatible with single element from the "items" type of the destination array parameter. 2. Source parameters which are arrays are concatenated. Source parameters which are single element types are appended as single elements. # Picking non-null values among inbound data links If present, `pickValue` specifies how to pick non-null values among inbound data links. `pickValue` is evaluated 1. Once all source values from upstream step or parameters are available. 2. After `linkMerge`. 3. Before `scatter` or `valueFrom`. This is specifically intended to be useful in combination with [conditional execution](#WorkflowStep), where several upstream steps may be connected to a single input (`source` is a list), and skipped steps produce null values. Static type checkers should check for type consistency after inferring what the type will be after `pickValue` is applied, just as they do currently for `linkMerge`. * **first_non_null** For the first level of a list input, pick the first non-null element. The result is a scalar. It is an error if there is no non-null element. Examples: * `[null, x, null, y] -> x` * `[null, [null], null, y] -> [null]` * `[null, null, null] -> Runtime Error` *Intended use case*: If-else pattern where the value comes either from a conditional step or from a default or fallback value. The conditional step(s) should be placed first in the list. * **the_only_non_null** For the first level of a list input, pick the single non-null element. The result is a scalar. It is an error if there is more than one non-null element. Examples: * `[null, x, null] -> x` * `[null, x, null, y] -> Runtime Error` * `[null, [null], null] -> [null]` * `[null, null, null] -> Runtime Error` *Intended use case*: Switch type patterns where developer considers more than one active code path as a workflow error (possibly indicating an error in writing `when` condition expressions). * **all_non_null** For the first level of a list input, pick all non-null values. The result is a list, which may be empty. Examples: * `[null, x, null] -> [x]` * `[x, null, y] -> [x, y]` * `[null, [x], [null]] -> [[x], [null]]` * `[null, null, null] -> []` *Intended use case*: It is valid to have more than one source, but sources are conditional, so null sources (from skipped steps) should be filtered out. """ id: str def __init__( self, id: Any, source: Optional[Any] = None, linkMerge: Optional[Any] = None, pickValue: Optional[Any] = None, loadContents: Optional[Any] = None, loadListing: Optional[Any] = None, label: Optional[Any] = None, default: Optional[Any] = None, valueFrom: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.id = id if id is not None else "_:" + str(_uuid__.uuid4()) self.source = source self.linkMerge = linkMerge self.pickValue = pickValue self.loadContents = loadContents self.loadListing = loadListing self.label = label self.default = default self.valueFrom = valueFrom def __eq__(self, other: Any) -> bool: if isinstance(other, WorkflowStepInput): return bool( self.id == other.id and self.source == other.source and self.linkMerge == other.linkMerge and self.pickValue == other.pickValue and self.loadContents == other.loadContents and self.loadListing == other.loadListing and self.label == other.label and self.default == other.default and self.valueFrom == other.valueFrom ) return False def __hash__(self) -> int: return hash( ( self.id, self.source, self.linkMerge, self.pickValue, self.loadContents, self.loadListing, self.label, self.default, self.valueFrom, ) ) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "WorkflowStepInput": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] id = None if "id" in _doc: try: id = load_field( _doc.get("id"), uri_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("id") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `id`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("id") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `id` field is not valid because:", SourceLine(_doc, "id", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `id` field is not valid because:", SourceLine(_doc, "id", str), [e], detailed_message=f"the `id` field with value `{val}` " "is not valid because:", ) ) __original_id_is_none = id is None if id is None: if docRoot is not None: id = docRoot else: _errors__.append(ValidationException("missing id")) if not __original_id_is_none: baseuri = cast(str, id) source = None if "source" in _doc: try: source = load_field( _doc.get("source"), uri_union_of_None_type_or_strtype_or_array_of_strtype_False_False_2_None, baseuri, loadingOptions, lc=_doc.get("source") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `source`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("source") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `source` field is not valid because:", SourceLine(_doc, "source", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `source` field is not valid because:", SourceLine(_doc, "source", str), [e], detailed_message=f"the `source` field with value `{val}` " "is not valid because:", ) ) linkMerge = None if "linkMerge" in _doc: try: linkMerge = load_field( _doc.get("linkMerge"), union_of_None_type_or_LinkMergeMethodLoader, baseuri, loadingOptions, lc=_doc.get("linkMerge") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `linkMerge`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("linkMerge") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `linkMerge` field is not valid because:", SourceLine(_doc, "linkMerge", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `linkMerge` field is not valid because:", SourceLine(_doc, "linkMerge", str), [e], detailed_message=f"the `linkMerge` field with value `{val}` " "is not valid because:", ) ) pickValue = None if "pickValue" in _doc: try: pickValue = load_field( _doc.get("pickValue"), union_of_None_type_or_PickValueMethodLoader, baseuri, loadingOptions, lc=_doc.get("pickValue") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `pickValue`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("pickValue") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `pickValue` field is not valid because:", SourceLine(_doc, "pickValue", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `pickValue` field is not valid because:", SourceLine(_doc, "pickValue", str), [e], detailed_message=f"the `pickValue` field with value `{val}` " "is not valid because:", ) ) loadContents = None if "loadContents" in _doc: try: loadContents = load_field( _doc.get("loadContents"), union_of_None_type_or_booltype, baseuri, loadingOptions, lc=_doc.get("loadContents") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `loadContents`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("loadContents") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `loadContents` field is not valid because:", SourceLine(_doc, "loadContents", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `loadContents` field is not valid because:", SourceLine(_doc, "loadContents", str), [e], detailed_message=f"the `loadContents` field with value `{val}` " "is not valid because:", ) ) loadListing = None if "loadListing" in _doc: try: loadListing = load_field( _doc.get("loadListing"), union_of_None_type_or_LoadListingEnumLoader, baseuri, loadingOptions, lc=_doc.get("loadListing") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `loadListing`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("loadListing") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `loadListing` field is not valid because:", SourceLine(_doc, "loadListing", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `loadListing` field is not valid because:", SourceLine(_doc, "loadListing", str), [e], detailed_message=f"the `loadListing` field with value `{val}` " "is not valid because:", ) ) label = None if "label" in _doc: try: label = load_field( _doc.get("label"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("label") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `label`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("label") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [e], detailed_message=f"the `label` field with value `{val}` " "is not valid because:", ) ) default = None if "default" in _doc: try: default = load_field( _doc.get("default"), union_of_None_type_or_CWLObjectTypeLoader, baseuri, loadingOptions, lc=_doc.get("default") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `default`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("default") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `default` field is not valid because:", SourceLine(_doc, "default", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `default` field is not valid because:", SourceLine(_doc, "default", str), [e], detailed_message=f"the `default` field with value `{val}` " "is not valid because:", ) ) valueFrom = None if "valueFrom" in _doc: try: valueFrom = load_field( _doc.get("valueFrom"), union_of_None_type_or_strtype_or_ExpressionLoader, baseuri, loadingOptions, lc=_doc.get("valueFrom") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `valueFrom`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("valueFrom") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `valueFrom` field is not valid because:", SourceLine(_doc, "valueFrom", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `valueFrom` field is not valid because:", SourceLine(_doc, "valueFrom", str), [e], detailed_message=f"the `valueFrom` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `id`, `source`, `linkMerge`, `pickValue`, `loadContents`, `loadListing`, `label`, `default`, `valueFrom`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( id=id, source=source, linkMerge=linkMerge, pickValue=pickValue, loadContents=loadContents, loadListing=loadListing, label=label, default=default, valueFrom=valueFrom, extension_fields=extension_fields, loadingOptions=loadingOptions, ) loadingOptions.idx[cast(str, id)] = (_constructed, loadingOptions) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.id is not None: u = save_relative_uri(self.id, base_url, True, None, relative_uris) r["id"] = u if self.source is not None: u = save_relative_uri(self.source, self.id, False, 2, relative_uris) r["source"] = u if self.linkMerge is not None: r["linkMerge"] = save( self.linkMerge, top=False, base_url=self.id, relative_uris=relative_uris ) if self.pickValue is not None: r["pickValue"] = save( self.pickValue, top=False, base_url=self.id, relative_uris=relative_uris ) if self.loadContents is not None: r["loadContents"] = save( self.loadContents, top=False, base_url=self.id, relative_uris=relative_uris, ) if self.loadListing is not None: r["loadListing"] = save( self.loadListing, top=False, base_url=self.id, relative_uris=relative_uris, ) if self.label is not None: r["label"] = save( self.label, top=False, base_url=self.id, relative_uris=relative_uris ) if self.default is not None: r["default"] = save( self.default, top=False, base_url=self.id, relative_uris=relative_uris ) if self.valueFrom is not None: r["valueFrom"] = save( self.valueFrom, top=False, base_url=self.id, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset( [ "id", "source", "linkMerge", "pickValue", "loadContents", "loadListing", "label", "default", "valueFrom", ] ) class WorkflowStepOutput(IdentifierRequired): """ Associate an output parameter of the underlying process with a workflow parameter. The workflow parameter (given in the `id` field) be may be used as a `source` to connect with input parameters of other workflow steps, or with an output parameter of the process. A unique identifier for this workflow output parameter. This is the identifier to use in the `source` field of `WorkflowStepInput` to connect the output value to downstream parameters. """ id: str def __init__( self, id: Any, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.id = id if id is not None else "_:" + str(_uuid__.uuid4()) def __eq__(self, other: Any) -> bool: if isinstance(other, WorkflowStepOutput): return bool(self.id == other.id) return False def __hash__(self) -> int: return hash((self.id)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "WorkflowStepOutput": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] id = None if "id" in _doc: try: id = load_field( _doc.get("id"), uri_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("id") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `id`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("id") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `id` field is not valid because:", SourceLine(_doc, "id", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `id` field is not valid because:", SourceLine(_doc, "id", str), [e], detailed_message=f"the `id` field with value `{val}` " "is not valid because:", ) ) __original_id_is_none = id is None if id is None: if docRoot is not None: id = docRoot else: _errors__.append(ValidationException("missing id")) if not __original_id_is_none: baseuri = cast(str, id) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `id`".format(k), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( id=id, extension_fields=extension_fields, loadingOptions=loadingOptions, ) loadingOptions.idx[cast(str, id)] = (_constructed, loadingOptions) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.id is not None: u = save_relative_uri(self.id, base_url, True, None, relative_uris) r["id"] = u # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["id"]) class WorkflowStep(IdentifierRequired, Labeled, Documented): """ A workflow step is an executable element of a workflow. It specifies the underlying process implementation (such as `CommandLineTool` or another `Workflow`) in the `run` field and connects the input and output parameters of the underlying process to workflow parameters. # Scatter/gather To use scatter/gather, [ScatterFeatureRequirement](#ScatterFeatureRequirement) must be specified in the workflow or workflow step requirements. A "scatter" operation specifies that the associated workflow step or subworkflow should execute separately over a list of input elements. Each job making up a scatter operation is independent and may be executed concurrently. The `scatter` field specifies one or more input parameters which will be scattered. An input parameter may be listed more than once. The declared type of each input parameter implicitly becomes an array of items of the input parameter type. If a parameter is listed more than once, it becomes a nested array. As a result, upstream parameters which are connected to scattered parameters must be arrays. All output parameter types are also implicitly wrapped in arrays. Each job in the scatter results in an entry in the output array. If any scattered parameter runtime value is an empty array, all outputs are set to empty arrays and no work is done for the step, according to applicable scattering rules. If `scatter` declares more than one input parameter, `scatterMethod` describes how to decompose the input into a discrete set of jobs. * **dotproduct** specifies that each of the input arrays are aligned and one element taken from each array to construct each job. It is an error if all input arrays are not the same length. * **nested_crossproduct** specifies the Cartesian product of the inputs, producing a job for every combination of the scattered inputs. The output must be nested arrays for each level of scattering, in the order that the input arrays are listed in the `scatter` field. * **flat_crossproduct** specifies the Cartesian product of the inputs, producing a job for every combination of the scattered inputs. The output arrays must be flattened to a single level, but otherwise listed in the order that the input arrays are listed in the `scatter` field. # Conditional execution (Optional) Conditional execution makes execution of a step conditional on an expression. A step that is not executed is "skipped". A skipped step produces `null` for all output parameters. The condition is evaluated after `scatter`, using the input object of each individual scatter job. This means over a set of scatter jobs, some may be executed and some may be skipped. When the results are gathered, skipped steps must be `null` in the output arrays. The `when` field controls conditional execution. This is an expression that must be evaluated with `inputs` bound to the step input object (or individual scatter job), and returns a boolean value. It is an error if this expression returns a value other than `true` or `false`. Conditionals in CWL are an optional feature and are not required to be implemented by all consumers of CWL documents. An implementation that does not support conditionals must return a fatal error when attempting to execute a workflow that uses conditional constructs the implementation does not support. # Subworkflows To specify a nested workflow as part of a workflow step, [SubworkflowFeatureRequirement](#SubworkflowFeatureRequirement) must be specified in the workflow or workflow step requirements. It is a fatal error if a workflow directly or indirectly invokes itself as a subworkflow (recursive workflows are not allowed). """ id: str def __init__( self, id: Any, in_: Any, out: Any, run: Any, label: Optional[Any] = None, doc: Optional[Any] = None, requirements: Optional[Any] = None, hints: Optional[Any] = None, when: Optional[Any] = None, scatter: Optional[Any] = None, scatterMethod: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.id = id if id is not None else "_:" + str(_uuid__.uuid4()) self.label = label self.doc = doc self.in_ = in_ self.out = out self.requirements = requirements self.hints = hints self.run = run self.when = when self.scatter = scatter self.scatterMethod = scatterMethod def __eq__(self, other: Any) -> bool: if isinstance(other, WorkflowStep): return bool( self.id == other.id and self.label == other.label and self.doc == other.doc and self.in_ == other.in_ and self.out == other.out and self.requirements == other.requirements and self.hints == other.hints and self.run == other.run and self.when == other.when and self.scatter == other.scatter and self.scatterMethod == other.scatterMethod ) return False def __hash__(self) -> int: return hash( ( self.id, self.label, self.doc, self.in_, self.out, self.requirements, self.hints, self.run, self.when, self.scatter, self.scatterMethod, ) ) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "WorkflowStep": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] id = None if "id" in _doc: try: id = load_field( _doc.get("id"), uri_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("id") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `id`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("id") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `id` field is not valid because:", SourceLine(_doc, "id", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `id` field is not valid because:", SourceLine(_doc, "id", str), [e], detailed_message=f"the `id` field with value `{val}` " "is not valid because:", ) ) __original_id_is_none = id is None if id is None: if docRoot is not None: id = docRoot else: _errors__.append(ValidationException("missing id")) if not __original_id_is_none: baseuri = cast(str, id) label = None if "label" in _doc: try: label = load_field( _doc.get("label"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("label") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `label`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("label") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [e], detailed_message=f"the `label` field with value `{val}` " "is not valid because:", ) ) doc = None if "doc" in _doc: try: doc = load_field( _doc.get("doc"), union_of_None_type_or_strtype_or_array_of_strtype, baseuri, loadingOptions, lc=_doc.get("doc") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `doc`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("doc") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [e], detailed_message=f"the `doc` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("in") is None: raise ValidationException("missing required field `in`", None, []) in_ = load_field( _doc.get("in"), idmap_in__array_of_WorkflowStepInputLoader, baseuri, loadingOptions, lc=_doc.get("in") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `in`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("in") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `in` field is not valid because:", SourceLine(_doc, "in", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `in` field is not valid because:", SourceLine(_doc, "in", str), [e], detailed_message=f"the `in` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("out") is None: raise ValidationException("missing required field `out`", None, []) out = load_field( _doc.get("out"), uri_union_of_array_of_union_of_strtype_or_WorkflowStepOutputLoader_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("out") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `out`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("out") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `out` field is not valid because:", SourceLine(_doc, "out", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `out` field is not valid because:", SourceLine(_doc, "out", str), [e], detailed_message=f"the `out` field with value `{val}` " "is not valid because:", ) ) requirements = None if "requirements" in _doc: try: requirements = load_field( _doc.get("requirements"), idmap_requirements_union_of_None_type_or_array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_LoadListingRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_WorkReuseLoader_or_NetworkAccessLoader_or_InplaceUpdateRequirementLoader_or_ToolTimeLimitLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader_or_SecretsLoader_or_MPIRequirementLoader_or_CUDARequirementLoader_or_LoopLoader_or_ShmSizeLoader, baseuri, loadingOptions, lc=_doc.get("requirements") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `requirements`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("requirements") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `requirements` field is not valid because:", SourceLine(_doc, "requirements", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `requirements` field is not valid because:", SourceLine(_doc, "requirements", str), [e], detailed_message=f"the `requirements` field with value `{val}` " "is not valid because:", ) ) hints = None if "hints" in _doc: try: hints = load_field( _doc.get("hints"), idmap_hints_union_of_None_type_or_array_of_Any_type, baseuri, loadingOptions, lc=_doc.get("hints") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `hints`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("hints") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `hints` field is not valid because:", SourceLine(_doc, "hints", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `hints` field is not valid because:", SourceLine(_doc, "hints", str), [e], detailed_message=f"the `hints` field with value `{val}` " "is not valid because:", ) ) subscope_baseuri = expand_url('run', baseuri, loadingOptions, True) try: if _doc.get("run") is None: raise ValidationException("missing required field `run`", None, []) run = load_field( _doc.get("run"), uri_union_of_strtype_or_CommandLineToolLoader_or_ExpressionToolLoader_or_WorkflowLoader_or_OperationLoader_or_ProcessGeneratorLoader_False_False_None_None, subscope_baseuri, loadingOptions, lc=_doc.get("run") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `run`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("run") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `run` field is not valid because:", SourceLine(_doc, "run", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `run` field is not valid because:", SourceLine(_doc, "run", str), [e], detailed_message=f"the `run` field with value `{val}` " "is not valid because:", ) ) when = None if "when" in _doc: try: when = load_field( _doc.get("when"), union_of_None_type_or_ExpressionLoader, baseuri, loadingOptions, lc=_doc.get("when") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `when`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("when") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `when` field is not valid because:", SourceLine(_doc, "when", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `when` field is not valid because:", SourceLine(_doc, "when", str), [e], detailed_message=f"the `when` field with value `{val}` " "is not valid because:", ) ) scatter = None if "scatter" in _doc: try: scatter = load_field( _doc.get("scatter"), uri_union_of_None_type_or_strtype_or_array_of_strtype_False_False_0_None, baseuri, loadingOptions, lc=_doc.get("scatter") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `scatter`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("scatter") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `scatter` field is not valid because:", SourceLine(_doc, "scatter", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `scatter` field is not valid because:", SourceLine(_doc, "scatter", str), [e], detailed_message=f"the `scatter` field with value `{val}` " "is not valid because:", ) ) scatterMethod = None if "scatterMethod" in _doc: try: scatterMethod = load_field( _doc.get("scatterMethod"), uri_union_of_None_type_or_ScatterMethodLoader_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("scatterMethod") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `scatterMethod`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("scatterMethod") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `scatterMethod` field is not valid because:", SourceLine(_doc, "scatterMethod", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `scatterMethod` field is not valid because:", SourceLine(_doc, "scatterMethod", str), [e], detailed_message=f"the `scatterMethod` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `id`, `label`, `doc`, `in`, `out`, `requirements`, `hints`, `run`, `when`, `scatter`, `scatterMethod`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( id=id, label=label, doc=doc, in_=in_, out=out, requirements=requirements, hints=hints, run=run, when=when, scatter=scatter, scatterMethod=scatterMethod, extension_fields=extension_fields, loadingOptions=loadingOptions, ) loadingOptions.idx[cast(str, id)] = (_constructed, loadingOptions) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.id is not None: u = save_relative_uri(self.id, base_url, True, None, relative_uris) r["id"] = u if self.label is not None: r["label"] = save( self.label, top=False, base_url=self.id, relative_uris=relative_uris ) if self.doc is not None: r["doc"] = save( self.doc, top=False, base_url=self.id, relative_uris=relative_uris ) if self.in_ is not None: r["in"] = save( self.in_, top=False, base_url=self.id, relative_uris=relative_uris ) if self.out is not None: u = save_relative_uri(self.out, self.id, True, None, relative_uris) r["out"] = u if self.requirements is not None: r["requirements"] = save( self.requirements, top=False, base_url=self.id, relative_uris=relative_uris, ) if self.hints is not None: r["hints"] = save( self.hints, top=False, base_url=self.id, relative_uris=relative_uris ) if self.run is not None: u = save_relative_uri(self.run, self.id, False, None, relative_uris) r["run"] = u if self.when is not None: r["when"] = save( self.when, top=False, base_url=self.id, relative_uris=relative_uris ) if self.scatter is not None: u = save_relative_uri(self.scatter, self.id, False, 0, relative_uris) r["scatter"] = u if self.scatterMethod is not None: u = save_relative_uri( self.scatterMethod, self.id, False, None, relative_uris ) r["scatterMethod"] = u # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset( [ "id", "label", "doc", "in", "out", "requirements", "hints", "run", "when", "scatter", "scatterMethod", ] ) class Workflow(Process): """ A workflow describes a set of **steps** and the **dependencies** between those steps. When a step produces output that will be consumed by a second step, the first step is a dependency of the second step. When there is a dependency, the workflow engine must execute the preceding step and wait for it to successfully produce output before executing the dependent step. If two steps are defined in the workflow graph that are not directly or indirectly dependent, these steps are **independent**, and may execute in any order or execute concurrently. A workflow is complete when all steps have been executed. Dependencies between parameters are expressed using the `source` field on [workflow step input parameters](#WorkflowStepInput) and `outputSource` field on [workflow output parameters](#WorkflowOutputParameter). The `source` field on each workflow step input parameter expresses the data links that contribute to the value of the step input parameter (the "sink"). A workflow step can only begin execution when every data link connected to a step has been fulfilled. The `outputSource` field on each workflow step input parameter expresses the data links that contribute to the value of the workflow output parameter (the "sink"). Workflow execution cannot complete successfully until every data link connected to an output parameter has been fulfilled. ## Workflow success and failure A completed step must result in one of `success`, `temporaryFailure` or `permanentFailure` states. An implementation may choose to retry a step execution which resulted in `temporaryFailure`. An implementation may choose to either continue running other steps of a workflow, or terminate immediately upon `permanentFailure`. * If any step of a workflow execution results in `permanentFailure`, then the workflow status is `permanentFailure`. * If one or more steps result in `temporaryFailure` and all other steps complete `success` or are not executed, then the workflow status is `temporaryFailure`. * If all workflow steps are executed and complete with `success`, then the workflow status is `success`. # Extensions [ScatterFeatureRequirement](#ScatterFeatureRequirement) and [SubworkflowFeatureRequirement](#SubworkflowFeatureRequirement) are available as standard [extensions](#Extensions_and_Metadata) to core workflow semantics. """ id: str def __init__( self, inputs: Any, outputs: Any, steps: Any, id: Optional[Any] = None, label: Optional[Any] = None, doc: Optional[Any] = None, requirements: Optional[Any] = None, hints: Optional[Any] = None, cwlVersion: Optional[Any] = None, intent: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.id = id if id is not None else "_:" + str(_uuid__.uuid4()) self.label = label self.doc = doc self.inputs = inputs self.outputs = outputs self.requirements = requirements self.hints = hints self.cwlVersion = cwlVersion self.intent = intent self.class_ = "Workflow" self.steps = steps def __eq__(self, other: Any) -> bool: if isinstance(other, Workflow): return bool( self.id == other.id and self.label == other.label and self.doc == other.doc and self.inputs == other.inputs and self.outputs == other.outputs and self.requirements == other.requirements and self.hints == other.hints and self.cwlVersion == other.cwlVersion and self.intent == other.intent and self.class_ == other.class_ and self.steps == other.steps ) return False def __hash__(self) -> int: return hash( ( self.id, self.label, self.doc, self.inputs, self.outputs, self.requirements, self.hints, self.cwlVersion, self.intent, self.class_, self.steps, ) ) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "Workflow": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] id = None if "id" in _doc: try: id = load_field( _doc.get("id"), uri_union_of_None_type_or_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("id") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `id`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("id") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `id` field is not valid because:", SourceLine(_doc, "id", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `id` field is not valid because:", SourceLine(_doc, "id", str), [e], detailed_message=f"the `id` field with value `{val}` " "is not valid because:", ) ) __original_id_is_none = id is None if id is None: if docRoot is not None: id = docRoot else: id = "_:" + str(_uuid__.uuid4()) if not __original_id_is_none: baseuri = cast(str, id) try: if _doc.get("class") is None: raise ValidationException("missing required field `class`", None, []) class_ = load_field( _doc.get("class"), uri_Workflow_classLoader_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("class") ) if class_ not in (cls.__name__, loadingOptions.vocab.get(cls.__name__)): raise ValidationException(f"tried `{cls.__name__}` but") except ValidationException as e: raise e label = None if "label" in _doc: try: label = load_field( _doc.get("label"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("label") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `label`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("label") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [e], detailed_message=f"the `label` field with value `{val}` " "is not valid because:", ) ) doc = None if "doc" in _doc: try: doc = load_field( _doc.get("doc"), union_of_None_type_or_strtype_or_array_of_strtype, baseuri, loadingOptions, lc=_doc.get("doc") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `doc`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("doc") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [e], detailed_message=f"the `doc` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("inputs") is None: raise ValidationException("missing required field `inputs`", None, []) inputs = load_field( _doc.get("inputs"), idmap_inputs_array_of_WorkflowInputParameterLoader, baseuri, loadingOptions, lc=_doc.get("inputs") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `inputs`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("inputs") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `inputs` field is not valid because:", SourceLine(_doc, "inputs", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `inputs` field is not valid because:", SourceLine(_doc, "inputs", str), [e], detailed_message=f"the `inputs` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("outputs") is None: raise ValidationException("missing required field `outputs`", None, []) outputs = load_field( _doc.get("outputs"), idmap_outputs_array_of_WorkflowOutputParameterLoader, baseuri, loadingOptions, lc=_doc.get("outputs") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `outputs`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("outputs") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `outputs` field is not valid because:", SourceLine(_doc, "outputs", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `outputs` field is not valid because:", SourceLine(_doc, "outputs", str), [e], detailed_message=f"the `outputs` field with value `{val}` " "is not valid because:", ) ) requirements = None if "requirements" in _doc: try: requirements = load_field( _doc.get("requirements"), idmap_requirements_union_of_None_type_or_array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_LoadListingRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_WorkReuseLoader_or_NetworkAccessLoader_or_InplaceUpdateRequirementLoader_or_ToolTimeLimitLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader_or_SecretsLoader_or_MPIRequirementLoader_or_CUDARequirementLoader_or_LoopLoader_or_ShmSizeLoader, baseuri, loadingOptions, lc=_doc.get("requirements") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `requirements`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("requirements") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `requirements` field is not valid because:", SourceLine(_doc, "requirements", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `requirements` field is not valid because:", SourceLine(_doc, "requirements", str), [e], detailed_message=f"the `requirements` field with value `{val}` " "is not valid because:", ) ) hints = None if "hints" in _doc: try: hints = load_field( _doc.get("hints"), idmap_hints_union_of_None_type_or_array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_LoadListingRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_WorkReuseLoader_or_NetworkAccessLoader_or_InplaceUpdateRequirementLoader_or_ToolTimeLimitLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader_or_SecretsLoader_or_MPIRequirementLoader_or_CUDARequirementLoader_or_LoopLoader_or_ShmSizeLoader_or_Any_type, baseuri, loadingOptions, lc=_doc.get("hints") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `hints`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("hints") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `hints` field is not valid because:", SourceLine(_doc, "hints", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `hints` field is not valid because:", SourceLine(_doc, "hints", str), [e], detailed_message=f"the `hints` field with value `{val}` " "is not valid because:", ) ) cwlVersion = None if "cwlVersion" in _doc: try: cwlVersion = load_field( _doc.get("cwlVersion"), uri_union_of_None_type_or_CWLVersionLoader_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("cwlVersion") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `cwlVersion`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("cwlVersion") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `cwlVersion` field is not valid because:", SourceLine(_doc, "cwlVersion", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `cwlVersion` field is not valid because:", SourceLine(_doc, "cwlVersion", str), [e], detailed_message=f"the `cwlVersion` field with value `{val}` " "is not valid because:", ) ) intent = None if "intent" in _doc: try: intent = load_field( _doc.get("intent"), uri_union_of_None_type_or_array_of_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("intent") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `intent`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("intent") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `intent` field is not valid because:", SourceLine(_doc, "intent", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `intent` field is not valid because:", SourceLine(_doc, "intent", str), [e], detailed_message=f"the `intent` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("steps") is None: raise ValidationException("missing required field `steps`", None, []) steps = load_field( _doc.get("steps"), idmap_steps_union_of_array_of_WorkflowStepLoader, baseuri, loadingOptions, lc=_doc.get("steps") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `steps`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("steps") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `steps` field is not valid because:", SourceLine(_doc, "steps", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `steps` field is not valid because:", SourceLine(_doc, "steps", str), [e], detailed_message=f"the `steps` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `id`, `label`, `doc`, `inputs`, `outputs`, `requirements`, `hints`, `cwlVersion`, `intent`, `class`, `steps`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( id=id, label=label, doc=doc, inputs=inputs, outputs=outputs, requirements=requirements, hints=hints, cwlVersion=cwlVersion, intent=intent, steps=steps, extension_fields=extension_fields, loadingOptions=loadingOptions, ) loadingOptions.idx[cast(str, id)] = (_constructed, loadingOptions) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.id is not None: u = save_relative_uri(self.id, base_url, True, None, relative_uris) r["id"] = u if self.class_ is not None: uri = self.loadingOptions.vocab[self.class_] if p := self.loadingOptions.rvocab.get(uri[: -len(self.class_)]): uri = f"{p}:{self.class_}" else: uri = self.class_ u = save_relative_uri(uri, self.id, False, None, relative_uris) r["class"] = u if self.label is not None: r["label"] = save( self.label, top=False, base_url=self.id, relative_uris=relative_uris ) if self.doc is not None: r["doc"] = save( self.doc, top=False, base_url=self.id, relative_uris=relative_uris ) if self.inputs is not None: r["inputs"] = save( self.inputs, top=False, base_url=self.id, relative_uris=relative_uris ) if self.outputs is not None: r["outputs"] = save( self.outputs, top=False, base_url=self.id, relative_uris=relative_uris ) if self.requirements is not None: r["requirements"] = save( self.requirements, top=False, base_url=self.id, relative_uris=relative_uris, ) if self.hints is not None: r["hints"] = save( self.hints, top=False, base_url=self.id, relative_uris=relative_uris ) if self.cwlVersion is not None: u = save_relative_uri(self.cwlVersion, self.id, False, None, relative_uris) r["cwlVersion"] = u if self.intent is not None: u = save_relative_uri(self.intent, self.id, True, None, relative_uris) r["intent"] = u if self.steps is not None: r["steps"] = save( self.steps, top=False, base_url=self.id, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset( [ "id", "label", "doc", "inputs", "outputs", "requirements", "hints", "cwlVersion", "intent", "class", "steps", ] ) class SubworkflowFeatureRequirement(ProcessRequirement): """ Indicates that the workflow platform must support nested workflows in the `run` field of [WorkflowStep](#WorkflowStep). """ def __init__( self, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.class_ = "SubworkflowFeatureRequirement" def __eq__(self, other: Any) -> bool: if isinstance(other, SubworkflowFeatureRequirement): return bool(self.class_ == other.class_) return False def __hash__(self) -> int: return hash((self.class_)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "SubworkflowFeatureRequirement": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("class") is None: raise ValidationException("missing required field `class`", None, []) class_ = load_field( _doc.get("class"), uri_SubworkflowFeatureRequirement_classLoader_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("class") ) if class_ not in (cls.__name__, loadingOptions.vocab.get(cls.__name__)): raise ValidationException(f"tried `{cls.__name__}` but") except ValidationException as e: raise e extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `class`".format(k), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.class_ is not None: uri = self.loadingOptions.vocab[self.class_] if p := self.loadingOptions.rvocab.get(uri[: -len(self.class_)]): uri = f"{p}:{self.class_}" else: uri = self.class_ u = save_relative_uri(uri, base_url, False, None, relative_uris) r["class"] = u # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["class"]) class ScatterFeatureRequirement(ProcessRequirement): """ Indicates that the workflow platform must support the `scatter` and `scatterMethod` fields of [WorkflowStep](#WorkflowStep). """ def __init__( self, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.class_ = "ScatterFeatureRequirement" def __eq__(self, other: Any) -> bool: if isinstance(other, ScatterFeatureRequirement): return bool(self.class_ == other.class_) return False def __hash__(self) -> int: return hash((self.class_)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "ScatterFeatureRequirement": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("class") is None: raise ValidationException("missing required field `class`", None, []) class_ = load_field( _doc.get("class"), uri_ScatterFeatureRequirement_classLoader_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("class") ) if class_ not in (cls.__name__, loadingOptions.vocab.get(cls.__name__)): raise ValidationException(f"tried `{cls.__name__}` but") except ValidationException as e: raise e extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `class`".format(k), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.class_ is not None: uri = self.loadingOptions.vocab[self.class_] if p := self.loadingOptions.rvocab.get(uri[: -len(self.class_)]): uri = f"{p}:{self.class_}" else: uri = self.class_ u = save_relative_uri(uri, base_url, False, None, relative_uris) r["class"] = u # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["class"]) class MultipleInputFeatureRequirement(ProcessRequirement): """ Indicates that the workflow platform must support multiple inbound data links listed in the `source` field of [WorkflowStepInput](#WorkflowStepInput). """ def __init__( self, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.class_ = "MultipleInputFeatureRequirement" def __eq__(self, other: Any) -> bool: if isinstance(other, MultipleInputFeatureRequirement): return bool(self.class_ == other.class_) return False def __hash__(self) -> int: return hash((self.class_)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "MultipleInputFeatureRequirement": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("class") is None: raise ValidationException("missing required field `class`", None, []) class_ = load_field( _doc.get("class"), uri_MultipleInputFeatureRequirement_classLoader_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("class") ) if class_ not in (cls.__name__, loadingOptions.vocab.get(cls.__name__)): raise ValidationException(f"tried `{cls.__name__}` but") except ValidationException as e: raise e extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `class`".format(k), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.class_ is not None: uri = self.loadingOptions.vocab[self.class_] if p := self.loadingOptions.rvocab.get(uri[: -len(self.class_)]): uri = f"{p}:{self.class_}" else: uri = self.class_ u = save_relative_uri(uri, base_url, False, None, relative_uris) r["class"] = u # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["class"]) class StepInputExpressionRequirement(ProcessRequirement): """ Indicate that the workflow platform must support the `valueFrom` field of [WorkflowStepInput](#WorkflowStepInput). """ def __init__( self, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.class_ = "StepInputExpressionRequirement" def __eq__(self, other: Any) -> bool: if isinstance(other, StepInputExpressionRequirement): return bool(self.class_ == other.class_) return False def __hash__(self) -> int: return hash((self.class_)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "StepInputExpressionRequirement": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("class") is None: raise ValidationException("missing required field `class`", None, []) class_ = load_field( _doc.get("class"), uri_StepInputExpressionRequirement_classLoader_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("class") ) if class_ not in (cls.__name__, loadingOptions.vocab.get(cls.__name__)): raise ValidationException(f"tried `{cls.__name__}` but") except ValidationException as e: raise e extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `class`".format(k), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.class_ is not None: uri = self.loadingOptions.vocab[self.class_] if p := self.loadingOptions.rvocab.get(uri[: -len(self.class_)]): uri = f"{p}:{self.class_}" else: uri = self.class_ u = save_relative_uri(uri, base_url, False, None, relative_uris) r["class"] = u # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["class"]) class OperationInputParameter(InputParameter): """ Describe an input parameter of an operation. """ id: str def __init__( self, id: Any, type_: Any, label: Optional[Any] = None, secondaryFiles: Optional[Any] = None, streamable: Optional[Any] = None, doc: Optional[Any] = None, format: Optional[Any] = None, loadContents: Optional[Any] = None, loadListing: Optional[Any] = None, default: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.label = label self.secondaryFiles = secondaryFiles self.streamable = streamable self.doc = doc self.id = id if id is not None else "_:" + str(_uuid__.uuid4()) self.format = format self.loadContents = loadContents self.loadListing = loadListing self.default = default self.type_ = type_ def __eq__(self, other: Any) -> bool: if isinstance(other, OperationInputParameter): return bool( self.label == other.label and self.secondaryFiles == other.secondaryFiles and self.streamable == other.streamable and self.doc == other.doc and self.id == other.id and self.format == other.format and self.loadContents == other.loadContents and self.loadListing == other.loadListing and self.default == other.default and self.type_ == other.type_ ) return False def __hash__(self) -> int: return hash( ( self.label, self.secondaryFiles, self.streamable, self.doc, self.id, self.format, self.loadContents, self.loadListing, self.default, self.type_, ) ) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "OperationInputParameter": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] id = None if "id" in _doc: try: id = load_field( _doc.get("id"), uri_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("id") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `id`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("id") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `id` field is not valid because:", SourceLine(_doc, "id", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `id` field is not valid because:", SourceLine(_doc, "id", str), [e], detailed_message=f"the `id` field with value `{val}` " "is not valid because:", ) ) __original_id_is_none = id is None if id is None: if docRoot is not None: id = docRoot else: _errors__.append(ValidationException("missing id")) if not __original_id_is_none: baseuri = cast(str, id) label = None if "label" in _doc: try: label = load_field( _doc.get("label"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("label") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `label`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("label") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [e], detailed_message=f"the `label` field with value `{val}` " "is not valid because:", ) ) secondaryFiles = None if "secondaryFiles" in _doc: try: secondaryFiles = load_field( _doc.get("secondaryFiles"), secondaryfilesdsl_union_of_None_type_or_SecondaryFileSchemaLoader_or_array_of_SecondaryFileSchemaLoader, baseuri, loadingOptions, lc=_doc.get("secondaryFiles") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `secondaryFiles`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("secondaryFiles") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `secondaryFiles` field is not valid because:", SourceLine(_doc, "secondaryFiles", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `secondaryFiles` field is not valid because:", SourceLine(_doc, "secondaryFiles", str), [e], detailed_message=f"the `secondaryFiles` field with value `{val}` " "is not valid because:", ) ) streamable = None if "streamable" in _doc: try: streamable = load_field( _doc.get("streamable"), union_of_None_type_or_booltype, baseuri, loadingOptions, lc=_doc.get("streamable") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `streamable`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("streamable") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `streamable` field is not valid because:", SourceLine(_doc, "streamable", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `streamable` field is not valid because:", SourceLine(_doc, "streamable", str), [e], detailed_message=f"the `streamable` field with value `{val}` " "is not valid because:", ) ) doc = None if "doc" in _doc: try: doc = load_field( _doc.get("doc"), union_of_None_type_or_strtype_or_array_of_strtype, baseuri, loadingOptions, lc=_doc.get("doc") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `doc`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("doc") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [e], detailed_message=f"the `doc` field with value `{val}` " "is not valid because:", ) ) format = None if "format" in _doc: try: format = load_field( _doc.get("format"), uri_union_of_None_type_or_strtype_or_array_of_strtype_or_ExpressionLoader_True_False_None_True, baseuri, loadingOptions, lc=_doc.get("format") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `format`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("format") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `format` field is not valid because:", SourceLine(_doc, "format", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `format` field is not valid because:", SourceLine(_doc, "format", str), [e], detailed_message=f"the `format` field with value `{val}` " "is not valid because:", ) ) loadContents = None if "loadContents" in _doc: try: loadContents = load_field( _doc.get("loadContents"), union_of_None_type_or_booltype, baseuri, loadingOptions, lc=_doc.get("loadContents") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `loadContents`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("loadContents") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `loadContents` field is not valid because:", SourceLine(_doc, "loadContents", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `loadContents` field is not valid because:", SourceLine(_doc, "loadContents", str), [e], detailed_message=f"the `loadContents` field with value `{val}` " "is not valid because:", ) ) loadListing = None if "loadListing" in _doc: try: loadListing = load_field( _doc.get("loadListing"), union_of_None_type_or_LoadListingEnumLoader, baseuri, loadingOptions, lc=_doc.get("loadListing") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `loadListing`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("loadListing") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `loadListing` field is not valid because:", SourceLine(_doc, "loadListing", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `loadListing` field is not valid because:", SourceLine(_doc, "loadListing", str), [e], detailed_message=f"the `loadListing` field with value `{val}` " "is not valid because:", ) ) default = None if "default" in _doc: try: default = load_field( _doc.get("default"), union_of_None_type_or_CWLObjectTypeLoader, baseuri, loadingOptions, lc=_doc.get("default") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `default`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("default") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `default` field is not valid because:", SourceLine(_doc, "default", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `default` field is not valid because:", SourceLine(_doc, "default", str), [e], detailed_message=f"the `default` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("type") is None: raise ValidationException("missing required field `type`", None, []) type_ = load_field( _doc.get("type"), typedsl_union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype_2, baseuri, loadingOptions, lc=_doc.get("type") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `type`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("type") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [e], detailed_message=f"the `type` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `label`, `secondaryFiles`, `streamable`, `doc`, `id`, `format`, `loadContents`, `loadListing`, `default`, `type`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( label=label, secondaryFiles=secondaryFiles, streamable=streamable, doc=doc, id=id, format=format, loadContents=loadContents, loadListing=loadListing, default=default, type_=type_, extension_fields=extension_fields, loadingOptions=loadingOptions, ) loadingOptions.idx[cast(str, id)] = (_constructed, loadingOptions) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.id is not None: u = save_relative_uri(self.id, base_url, True, None, relative_uris) r["id"] = u if self.label is not None: r["label"] = save( self.label, top=False, base_url=self.id, relative_uris=relative_uris ) if self.secondaryFiles is not None: r["secondaryFiles"] = save( self.secondaryFiles, top=False, base_url=self.id, relative_uris=relative_uris, ) if self.streamable is not None: r["streamable"] = save( self.streamable, top=False, base_url=self.id, relative_uris=relative_uris, ) if self.doc is not None: r["doc"] = save( self.doc, top=False, base_url=self.id, relative_uris=relative_uris ) if self.format is not None: u = save_relative_uri(self.format, self.id, True, None, relative_uris) r["format"] = u if self.loadContents is not None: r["loadContents"] = save( self.loadContents, top=False, base_url=self.id, relative_uris=relative_uris, ) if self.loadListing is not None: r["loadListing"] = save( self.loadListing, top=False, base_url=self.id, relative_uris=relative_uris, ) if self.default is not None: r["default"] = save( self.default, top=False, base_url=self.id, relative_uris=relative_uris ) if self.type_ is not None: r["type"] = save( self.type_, top=False, base_url=self.id, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset( [ "label", "secondaryFiles", "streamable", "doc", "id", "format", "loadContents", "loadListing", "default", "type", ] ) class OperationOutputParameter(OutputParameter): """ Describe an output parameter of an operation. """ id: str def __init__( self, id: Any, type_: Any, label: Optional[Any] = None, secondaryFiles: Optional[Any] = None, streamable: Optional[Any] = None, doc: Optional[Any] = None, format: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.label = label self.secondaryFiles = secondaryFiles self.streamable = streamable self.doc = doc self.id = id if id is not None else "_:" + str(_uuid__.uuid4()) self.format = format self.type_ = type_ def __eq__(self, other: Any) -> bool: if isinstance(other, OperationOutputParameter): return bool( self.label == other.label and self.secondaryFiles == other.secondaryFiles and self.streamable == other.streamable and self.doc == other.doc and self.id == other.id and self.format == other.format and self.type_ == other.type_ ) return False def __hash__(self) -> int: return hash( ( self.label, self.secondaryFiles, self.streamable, self.doc, self.id, self.format, self.type_, ) ) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "OperationOutputParameter": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] id = None if "id" in _doc: try: id = load_field( _doc.get("id"), uri_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("id") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `id`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("id") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `id` field is not valid because:", SourceLine(_doc, "id", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `id` field is not valid because:", SourceLine(_doc, "id", str), [e], detailed_message=f"the `id` field with value `{val}` " "is not valid because:", ) ) __original_id_is_none = id is None if id is None: if docRoot is not None: id = docRoot else: _errors__.append(ValidationException("missing id")) if not __original_id_is_none: baseuri = cast(str, id) label = None if "label" in _doc: try: label = load_field( _doc.get("label"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("label") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `label`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("label") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [e], detailed_message=f"the `label` field with value `{val}` " "is not valid because:", ) ) secondaryFiles = None if "secondaryFiles" in _doc: try: secondaryFiles = load_field( _doc.get("secondaryFiles"), secondaryfilesdsl_union_of_None_type_or_SecondaryFileSchemaLoader_or_array_of_SecondaryFileSchemaLoader, baseuri, loadingOptions, lc=_doc.get("secondaryFiles") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `secondaryFiles`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("secondaryFiles") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `secondaryFiles` field is not valid because:", SourceLine(_doc, "secondaryFiles", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `secondaryFiles` field is not valid because:", SourceLine(_doc, "secondaryFiles", str), [e], detailed_message=f"the `secondaryFiles` field with value `{val}` " "is not valid because:", ) ) streamable = None if "streamable" in _doc: try: streamable = load_field( _doc.get("streamable"), union_of_None_type_or_booltype, baseuri, loadingOptions, lc=_doc.get("streamable") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `streamable`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("streamable") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `streamable` field is not valid because:", SourceLine(_doc, "streamable", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `streamable` field is not valid because:", SourceLine(_doc, "streamable", str), [e], detailed_message=f"the `streamable` field with value `{val}` " "is not valid because:", ) ) doc = None if "doc" in _doc: try: doc = load_field( _doc.get("doc"), union_of_None_type_or_strtype_or_array_of_strtype, baseuri, loadingOptions, lc=_doc.get("doc") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `doc`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("doc") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [e], detailed_message=f"the `doc` field with value `{val}` " "is not valid because:", ) ) format = None if "format" in _doc: try: format = load_field( _doc.get("format"), uri_union_of_None_type_or_strtype_or_ExpressionLoader_True_False_None_True, baseuri, loadingOptions, lc=_doc.get("format") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `format`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("format") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `format` field is not valid because:", SourceLine(_doc, "format", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `format` field is not valid because:", SourceLine(_doc, "format", str), [e], detailed_message=f"the `format` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("type") is None: raise ValidationException("missing required field `type`", None, []) type_ = load_field( _doc.get("type"), typedsl_union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype_2, baseuri, loadingOptions, lc=_doc.get("type") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `type`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("type") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `type` field is not valid because:", SourceLine(_doc, "type", str), [e], detailed_message=f"the `type` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `label`, `secondaryFiles`, `streamable`, `doc`, `id`, `format`, `type`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( label=label, secondaryFiles=secondaryFiles, streamable=streamable, doc=doc, id=id, format=format, type_=type_, extension_fields=extension_fields, loadingOptions=loadingOptions, ) loadingOptions.idx[cast(str, id)] = (_constructed, loadingOptions) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.id is not None: u = save_relative_uri(self.id, base_url, True, None, relative_uris) r["id"] = u if self.label is not None: r["label"] = save( self.label, top=False, base_url=self.id, relative_uris=relative_uris ) if self.secondaryFiles is not None: r["secondaryFiles"] = save( self.secondaryFiles, top=False, base_url=self.id, relative_uris=relative_uris, ) if self.streamable is not None: r["streamable"] = save( self.streamable, top=False, base_url=self.id, relative_uris=relative_uris, ) if self.doc is not None: r["doc"] = save( self.doc, top=False, base_url=self.id, relative_uris=relative_uris ) if self.format is not None: u = save_relative_uri(self.format, self.id, True, None, relative_uris) r["format"] = u if self.type_ is not None: r["type"] = save( self.type_, top=False, base_url=self.id, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset( ["label", "secondaryFiles", "streamable", "doc", "id", "format", "type"] ) class Operation(Process): """ This record describes an abstract operation. It is a potential step of a workflow that has not yet been bound to a concrete implementation. It specifies an input and output signature, but does not provide enough information to be executed. An implementation (or other tooling) may provide a means of binding an Operation to a concrete process (such as Workflow, CommandLineTool, or ExpressionTool) with a compatible signature. """ id: str def __init__( self, inputs: Any, outputs: Any, id: Optional[Any] = None, label: Optional[Any] = None, doc: Optional[Any] = None, requirements: Optional[Any] = None, hints: Optional[Any] = None, cwlVersion: Optional[Any] = None, intent: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.id = id if id is not None else "_:" + str(_uuid__.uuid4()) self.label = label self.doc = doc self.inputs = inputs self.outputs = outputs self.requirements = requirements self.hints = hints self.cwlVersion = cwlVersion self.intent = intent self.class_ = "Operation" def __eq__(self, other: Any) -> bool: if isinstance(other, Operation): return bool( self.id == other.id and self.label == other.label and self.doc == other.doc and self.inputs == other.inputs and self.outputs == other.outputs and self.requirements == other.requirements and self.hints == other.hints and self.cwlVersion == other.cwlVersion and self.intent == other.intent and self.class_ == other.class_ ) return False def __hash__(self) -> int: return hash( ( self.id, self.label, self.doc, self.inputs, self.outputs, self.requirements, self.hints, self.cwlVersion, self.intent, self.class_, ) ) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "Operation": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] id = None if "id" in _doc: try: id = load_field( _doc.get("id"), uri_union_of_None_type_or_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("id") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `id`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("id") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `id` field is not valid because:", SourceLine(_doc, "id", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `id` field is not valid because:", SourceLine(_doc, "id", str), [e], detailed_message=f"the `id` field with value `{val}` " "is not valid because:", ) ) __original_id_is_none = id is None if id is None: if docRoot is not None: id = docRoot else: id = "_:" + str(_uuid__.uuid4()) if not __original_id_is_none: baseuri = cast(str, id) try: if _doc.get("class") is None: raise ValidationException("missing required field `class`", None, []) class_ = load_field( _doc.get("class"), uri_Operation_classLoader_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("class") ) if class_ not in (cls.__name__, loadingOptions.vocab.get(cls.__name__)): raise ValidationException(f"tried `{cls.__name__}` but") except ValidationException as e: raise e label = None if "label" in _doc: try: label = load_field( _doc.get("label"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("label") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `label`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("label") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [e], detailed_message=f"the `label` field with value `{val}` " "is not valid because:", ) ) doc = None if "doc" in _doc: try: doc = load_field( _doc.get("doc"), union_of_None_type_or_strtype_or_array_of_strtype, baseuri, loadingOptions, lc=_doc.get("doc") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `doc`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("doc") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [e], detailed_message=f"the `doc` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("inputs") is None: raise ValidationException("missing required field `inputs`", None, []) inputs = load_field( _doc.get("inputs"), idmap_inputs_array_of_OperationInputParameterLoader, baseuri, loadingOptions, lc=_doc.get("inputs") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `inputs`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("inputs") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `inputs` field is not valid because:", SourceLine(_doc, "inputs", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `inputs` field is not valid because:", SourceLine(_doc, "inputs", str), [e], detailed_message=f"the `inputs` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("outputs") is None: raise ValidationException("missing required field `outputs`", None, []) outputs = load_field( _doc.get("outputs"), idmap_outputs_array_of_OperationOutputParameterLoader, baseuri, loadingOptions, lc=_doc.get("outputs") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `outputs`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("outputs") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `outputs` field is not valid because:", SourceLine(_doc, "outputs", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `outputs` field is not valid because:", SourceLine(_doc, "outputs", str), [e], detailed_message=f"the `outputs` field with value `{val}` " "is not valid because:", ) ) requirements = None if "requirements" in _doc: try: requirements = load_field( _doc.get("requirements"), idmap_requirements_union_of_None_type_or_array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_LoadListingRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_WorkReuseLoader_or_NetworkAccessLoader_or_InplaceUpdateRequirementLoader_or_ToolTimeLimitLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader_or_SecretsLoader_or_MPIRequirementLoader_or_CUDARequirementLoader_or_LoopLoader_or_ShmSizeLoader, baseuri, loadingOptions, lc=_doc.get("requirements") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `requirements`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("requirements") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `requirements` field is not valid because:", SourceLine(_doc, "requirements", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `requirements` field is not valid because:", SourceLine(_doc, "requirements", str), [e], detailed_message=f"the `requirements` field with value `{val}` " "is not valid because:", ) ) hints = None if "hints" in _doc: try: hints = load_field( _doc.get("hints"), idmap_hints_union_of_None_type_or_array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_LoadListingRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_WorkReuseLoader_or_NetworkAccessLoader_or_InplaceUpdateRequirementLoader_or_ToolTimeLimitLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader_or_SecretsLoader_or_MPIRequirementLoader_or_CUDARequirementLoader_or_LoopLoader_or_ShmSizeLoader_or_Any_type, baseuri, loadingOptions, lc=_doc.get("hints") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `hints`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("hints") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `hints` field is not valid because:", SourceLine(_doc, "hints", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `hints` field is not valid because:", SourceLine(_doc, "hints", str), [e], detailed_message=f"the `hints` field with value `{val}` " "is not valid because:", ) ) cwlVersion = None if "cwlVersion" in _doc: try: cwlVersion = load_field( _doc.get("cwlVersion"), uri_union_of_None_type_or_CWLVersionLoader_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("cwlVersion") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `cwlVersion`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("cwlVersion") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `cwlVersion` field is not valid because:", SourceLine(_doc, "cwlVersion", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `cwlVersion` field is not valid because:", SourceLine(_doc, "cwlVersion", str), [e], detailed_message=f"the `cwlVersion` field with value `{val}` " "is not valid because:", ) ) intent = None if "intent" in _doc: try: intent = load_field( _doc.get("intent"), uri_union_of_None_type_or_array_of_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("intent") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `intent`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("intent") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `intent` field is not valid because:", SourceLine(_doc, "intent", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `intent` field is not valid because:", SourceLine(_doc, "intent", str), [e], detailed_message=f"the `intent` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `id`, `label`, `doc`, `inputs`, `outputs`, `requirements`, `hints`, `cwlVersion`, `intent`, `class`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( id=id, label=label, doc=doc, inputs=inputs, outputs=outputs, requirements=requirements, hints=hints, cwlVersion=cwlVersion, intent=intent, extension_fields=extension_fields, loadingOptions=loadingOptions, ) loadingOptions.idx[cast(str, id)] = (_constructed, loadingOptions) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.id is not None: u = save_relative_uri(self.id, base_url, True, None, relative_uris) r["id"] = u if self.class_ is not None: uri = self.loadingOptions.vocab[self.class_] if p := self.loadingOptions.rvocab.get(uri[: -len(self.class_)]): uri = f"{p}:{self.class_}" else: uri = self.class_ u = save_relative_uri(uri, self.id, False, None, relative_uris) r["class"] = u if self.label is not None: r["label"] = save( self.label, top=False, base_url=self.id, relative_uris=relative_uris ) if self.doc is not None: r["doc"] = save( self.doc, top=False, base_url=self.id, relative_uris=relative_uris ) if self.inputs is not None: r["inputs"] = save( self.inputs, top=False, base_url=self.id, relative_uris=relative_uris ) if self.outputs is not None: r["outputs"] = save( self.outputs, top=False, base_url=self.id, relative_uris=relative_uris ) if self.requirements is not None: r["requirements"] = save( self.requirements, top=False, base_url=self.id, relative_uris=relative_uris, ) if self.hints is not None: r["hints"] = save( self.hints, top=False, base_url=self.id, relative_uris=relative_uris ) if self.cwlVersion is not None: u = save_relative_uri(self.cwlVersion, self.id, False, None, relative_uris) r["cwlVersion"] = u if self.intent is not None: u = save_relative_uri(self.intent, self.id, True, None, relative_uris) r["intent"] = u # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset( [ "id", "label", "doc", "inputs", "outputs", "requirements", "hints", "cwlVersion", "intent", "class", ] ) class Secrets(ProcessRequirement): def __init__( self, secrets: Any, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.class_ = "Secrets" self.secrets = secrets def __eq__(self, other: Any) -> bool: if isinstance(other, Secrets): return bool(self.class_ == other.class_ and self.secrets == other.secrets) return False def __hash__(self) -> int: return hash((self.class_, self.secrets)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "Secrets": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("class") is None: raise ValidationException("missing required field `class`", None, []) class_ = load_field( _doc.get("class"), uri_strtype_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("class") ) if class_ not in (cls.__name__, loadingOptions.vocab.get(cls.__name__)): raise ValidationException(f"tried `{cls.__name__}` but") except ValidationException as e: raise e try: if _doc.get("secrets") is None: raise ValidationException("missing required field `secrets`", None, []) secrets = load_field( _doc.get("secrets"), uri_array_of_strtype_False_False_0_None, baseuri, loadingOptions, lc=_doc.get("secrets") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `secrets`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("secrets") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `secrets` field is not valid because:", SourceLine(_doc, "secrets", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `secrets` field is not valid because:", SourceLine(_doc, "secrets", str), [e], detailed_message=f"the `secrets` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `class`, `secrets`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( secrets=secrets, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.class_ is not None: uri = self.loadingOptions.vocab[self.class_] if p := self.loadingOptions.rvocab.get(uri[: -len(self.class_)]): uri = f"{p}:{self.class_}" else: uri = self.class_ u = save_relative_uri(uri, base_url, False, None, relative_uris) r["class"] = u if self.secrets is not None: u = save_relative_uri(self.secrets, base_url, False, 0, relative_uris) r["secrets"] = u # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["class", "secrets"]) class ProcessGenerator(Process): id: str def __init__( self, inputs: Any, outputs: Any, run: Any, id: Optional[Any] = None, label: Optional[Any] = None, doc: Optional[Any] = None, requirements: Optional[Any] = None, hints: Optional[Any] = None, cwlVersion: Optional[Any] = None, intent: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.id = id if id is not None else "_:" + str(_uuid__.uuid4()) self.label = label self.doc = doc self.inputs = inputs self.outputs = outputs self.requirements = requirements self.hints = hints self.cwlVersion = cwlVersion self.intent = intent self.class_ = "ProcessGenerator" self.run = run def __eq__(self, other: Any) -> bool: if isinstance(other, ProcessGenerator): return bool( self.id == other.id and self.label == other.label and self.doc == other.doc and self.inputs == other.inputs and self.outputs == other.outputs and self.requirements == other.requirements and self.hints == other.hints and self.cwlVersion == other.cwlVersion and self.intent == other.intent and self.class_ == other.class_ and self.run == other.run ) return False def __hash__(self) -> int: return hash( ( self.id, self.label, self.doc, self.inputs, self.outputs, self.requirements, self.hints, self.cwlVersion, self.intent, self.class_, self.run, ) ) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "ProcessGenerator": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] id = None if "id" in _doc: try: id = load_field( _doc.get("id"), uri_union_of_None_type_or_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("id") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `id`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("id") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `id` field is not valid because:", SourceLine(_doc, "id", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `id` field is not valid because:", SourceLine(_doc, "id", str), [e], detailed_message=f"the `id` field with value `{val}` " "is not valid because:", ) ) __original_id_is_none = id is None if id is None: if docRoot is not None: id = docRoot else: id = "_:" + str(_uuid__.uuid4()) if not __original_id_is_none: baseuri = cast(str, id) try: if _doc.get("class") is None: raise ValidationException("missing required field `class`", None, []) class_ = load_field( _doc.get("class"), uri_strtype_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("class") ) if class_ not in (cls.__name__, loadingOptions.vocab.get(cls.__name__)): raise ValidationException(f"tried `{cls.__name__}` but") except ValidationException as e: raise e label = None if "label" in _doc: try: label = load_field( _doc.get("label"), union_of_None_type_or_strtype, baseuri, loadingOptions, lc=_doc.get("label") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `label`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("label") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `label` field is not valid because:", SourceLine(_doc, "label", str), [e], detailed_message=f"the `label` field with value `{val}` " "is not valid because:", ) ) doc = None if "doc" in _doc: try: doc = load_field( _doc.get("doc"), union_of_None_type_or_strtype_or_array_of_strtype, baseuri, loadingOptions, lc=_doc.get("doc") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `doc`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("doc") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `doc` field is not valid because:", SourceLine(_doc, "doc", str), [e], detailed_message=f"the `doc` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("inputs") is None: raise ValidationException("missing required field `inputs`", None, []) inputs = load_field( _doc.get("inputs"), idmap_inputs_array_of_union_of_CommandInputParameterLoader_or_WorkflowInputParameterLoader_or_OperationInputParameterLoader, baseuri, loadingOptions, lc=_doc.get("inputs") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `inputs`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("inputs") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `inputs` field is not valid because:", SourceLine(_doc, "inputs", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `inputs` field is not valid because:", SourceLine(_doc, "inputs", str), [e], detailed_message=f"the `inputs` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("outputs") is None: raise ValidationException("missing required field `outputs`", None, []) outputs = load_field( _doc.get("outputs"), idmap_outputs_array_of_union_of_CommandOutputParameterLoader_or_ExpressionToolOutputParameterLoader_or_WorkflowOutputParameterLoader_or_OperationOutputParameterLoader, baseuri, loadingOptions, lc=_doc.get("outputs") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `outputs`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("outputs") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `outputs` field is not valid because:", SourceLine(_doc, "outputs", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `outputs` field is not valid because:", SourceLine(_doc, "outputs", str), [e], detailed_message=f"the `outputs` field with value `{val}` " "is not valid because:", ) ) requirements = None if "requirements" in _doc: try: requirements = load_field( _doc.get("requirements"), idmap_requirements_union_of_None_type_or_array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_LoadListingRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_WorkReuseLoader_or_NetworkAccessLoader_or_InplaceUpdateRequirementLoader_or_ToolTimeLimitLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader_or_SecretsLoader_or_MPIRequirementLoader_or_CUDARequirementLoader_or_LoopLoader_or_ShmSizeLoader, baseuri, loadingOptions, lc=_doc.get("requirements") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `requirements`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("requirements") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `requirements` field is not valid because:", SourceLine(_doc, "requirements", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `requirements` field is not valid because:", SourceLine(_doc, "requirements", str), [e], detailed_message=f"the `requirements` field with value `{val}` " "is not valid because:", ) ) hints = None if "hints" in _doc: try: hints = load_field( _doc.get("hints"), idmap_hints_union_of_None_type_or_array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_LoadListingRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_WorkReuseLoader_or_NetworkAccessLoader_or_InplaceUpdateRequirementLoader_or_ToolTimeLimitLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader_or_SecretsLoader_or_MPIRequirementLoader_or_CUDARequirementLoader_or_LoopLoader_or_ShmSizeLoader_or_Any_type, baseuri, loadingOptions, lc=_doc.get("hints") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `hints`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("hints") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `hints` field is not valid because:", SourceLine(_doc, "hints", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `hints` field is not valid because:", SourceLine(_doc, "hints", str), [e], detailed_message=f"the `hints` field with value `{val}` " "is not valid because:", ) ) cwlVersion = None if "cwlVersion" in _doc: try: cwlVersion = load_field( _doc.get("cwlVersion"), uri_union_of_None_type_or_CWLVersionLoader_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("cwlVersion") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `cwlVersion`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("cwlVersion") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `cwlVersion` field is not valid because:", SourceLine(_doc, "cwlVersion", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `cwlVersion` field is not valid because:", SourceLine(_doc, "cwlVersion", str), [e], detailed_message=f"the `cwlVersion` field with value `{val}` " "is not valid because:", ) ) intent = None if "intent" in _doc: try: intent = load_field( _doc.get("intent"), uri_union_of_None_type_or_array_of_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("intent") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `intent`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("intent") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `intent` field is not valid because:", SourceLine(_doc, "intent", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `intent` field is not valid because:", SourceLine(_doc, "intent", str), [e], detailed_message=f"the `intent` field with value `{val}` " "is not valid because:", ) ) subscope_baseuri = expand_url('run', baseuri, loadingOptions, True) try: if _doc.get("run") is None: raise ValidationException("missing required field `run`", None, []) run = load_field( _doc.get("run"), uri_union_of_strtype_or_CommandLineToolLoader_or_ExpressionToolLoader_or_WorkflowLoader_or_OperationLoader_or_ProcessGeneratorLoader_False_False_None_None, subscope_baseuri, loadingOptions, lc=_doc.get("run") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `run`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("run") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `run` field is not valid because:", SourceLine(_doc, "run", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `run` field is not valid because:", SourceLine(_doc, "run", str), [e], detailed_message=f"the `run` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `id`, `label`, `doc`, `inputs`, `outputs`, `requirements`, `hints`, `cwlVersion`, `intent`, `class`, `run`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( id=id, label=label, doc=doc, inputs=inputs, outputs=outputs, requirements=requirements, hints=hints, cwlVersion=cwlVersion, intent=intent, run=run, extension_fields=extension_fields, loadingOptions=loadingOptions, ) loadingOptions.idx[cast(str, id)] = (_constructed, loadingOptions) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.id is not None: u = save_relative_uri(self.id, base_url, True, None, relative_uris) r["id"] = u if self.class_ is not None: uri = self.loadingOptions.vocab[self.class_] if p := self.loadingOptions.rvocab.get(uri[: -len(self.class_)]): uri = f"{p}:{self.class_}" else: uri = self.class_ u = save_relative_uri(uri, self.id, False, None, relative_uris) r["class"] = u if self.label is not None: r["label"] = save( self.label, top=False, base_url=self.id, relative_uris=relative_uris ) if self.doc is not None: r["doc"] = save( self.doc, top=False, base_url=self.id, relative_uris=relative_uris ) if self.inputs is not None: r["inputs"] = save( self.inputs, top=False, base_url=self.id, relative_uris=relative_uris ) if self.outputs is not None: r["outputs"] = save( self.outputs, top=False, base_url=self.id, relative_uris=relative_uris ) if self.requirements is not None: r["requirements"] = save( self.requirements, top=False, base_url=self.id, relative_uris=relative_uris, ) if self.hints is not None: r["hints"] = save( self.hints, top=False, base_url=self.id, relative_uris=relative_uris ) if self.cwlVersion is not None: u = save_relative_uri(self.cwlVersion, self.id, False, None, relative_uris) r["cwlVersion"] = u if self.intent is not None: u = save_relative_uri(self.intent, self.id, True, None, relative_uris) r["intent"] = u if self.run is not None: u = save_relative_uri(self.run, self.id, False, None, relative_uris) r["run"] = u # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset( [ "id", "label", "doc", "inputs", "outputs", "requirements", "hints", "cwlVersion", "intent", "class", "run", ] ) class MPIRequirement(ProcessRequirement): """ Indicates that a process requires an MPI runtime. """ def __init__( self, processes: Any, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.class_ = "MPIRequirement" self.processes = processes def __eq__(self, other: Any) -> bool: if isinstance(other, MPIRequirement): return bool( self.class_ == other.class_ and self.processes == other.processes ) return False def __hash__(self) -> int: return hash((self.class_, self.processes)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "MPIRequirement": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("class") is None: raise ValidationException("missing required field `class`", None, []) class_ = load_field( _doc.get("class"), uri_strtype_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("class") ) if class_ not in (cls.__name__, loadingOptions.vocab.get(cls.__name__)): raise ValidationException(f"tried `{cls.__name__}` but") except ValidationException as e: raise e try: if _doc.get("processes") is None: raise ValidationException("missing required field `processes`", None, []) processes = load_field( _doc.get("processes"), union_of_inttype_or_ExpressionLoader, baseuri, loadingOptions, lc=_doc.get("processes") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `processes`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("processes") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `processes` field is not valid because:", SourceLine(_doc, "processes", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `processes` field is not valid because:", SourceLine(_doc, "processes", str), [e], detailed_message=f"the `processes` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `class`, `processes`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( processes=processes, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.class_ is not None: uri = self.loadingOptions.vocab[self.class_] if p := self.loadingOptions.rvocab.get(uri[: -len(self.class_)]): uri = f"{p}:{self.class_}" else: uri = self.class_ u = save_relative_uri(uri, base_url, False, None, relative_uris) r["class"] = u if self.processes is not None: r["processes"] = save( self.processes, top=False, base_url=base_url, relative_uris=relative_uris, ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["class", "processes"]) class CUDARequirement(ProcessRequirement): """ Require support for NVIDA CUDA (GPU hardware acceleration). """ def __init__( self, cudaComputeCapability: Any, cudaVersionMin: Any, cudaDeviceCountMax: Optional[Any] = None, cudaDeviceCountMin: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.class_ = "CUDARequirement" self.cudaComputeCapability = cudaComputeCapability self.cudaDeviceCountMax = cudaDeviceCountMax self.cudaDeviceCountMin = cudaDeviceCountMin self.cudaVersionMin = cudaVersionMin def __eq__(self, other: Any) -> bool: if isinstance(other, CUDARequirement): return bool( self.class_ == other.class_ and self.cudaComputeCapability == other.cudaComputeCapability and self.cudaDeviceCountMax == other.cudaDeviceCountMax and self.cudaDeviceCountMin == other.cudaDeviceCountMin and self.cudaVersionMin == other.cudaVersionMin ) return False def __hash__(self) -> int: return hash( ( self.class_, self.cudaComputeCapability, self.cudaDeviceCountMax, self.cudaDeviceCountMin, self.cudaVersionMin, ) ) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "CUDARequirement": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("class") is None: raise ValidationException("missing required field `class`", None, []) class_ = load_field( _doc.get("class"), uri_strtype_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("class") ) if class_ not in (cls.__name__, loadingOptions.vocab.get(cls.__name__)): raise ValidationException(f"tried `{cls.__name__}` but") except ValidationException as e: raise e try: if _doc.get("cudaComputeCapability") is None: raise ValidationException("missing required field `cudaComputeCapability`", None, []) cudaComputeCapability = load_field( _doc.get("cudaComputeCapability"), union_of_strtype_or_array_of_strtype, baseuri, loadingOptions, lc=_doc.get("cudaComputeCapability") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `cudaComputeCapability`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("cudaComputeCapability") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `cudaComputeCapability` field is not valid because:", SourceLine(_doc, "cudaComputeCapability", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `cudaComputeCapability` field is not valid because:", SourceLine(_doc, "cudaComputeCapability", str), [e], detailed_message=f"the `cudaComputeCapability` field with value `{val}` " "is not valid because:", ) ) cudaDeviceCountMax = None if "cudaDeviceCountMax" in _doc: try: cudaDeviceCountMax = load_field( _doc.get("cudaDeviceCountMax"), union_of_None_type_or_inttype_or_ExpressionLoader, baseuri, loadingOptions, lc=_doc.get("cudaDeviceCountMax") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `cudaDeviceCountMax`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("cudaDeviceCountMax") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `cudaDeviceCountMax` field is not valid because:", SourceLine(_doc, "cudaDeviceCountMax", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `cudaDeviceCountMax` field is not valid because:", SourceLine(_doc, "cudaDeviceCountMax", str), [e], detailed_message=f"the `cudaDeviceCountMax` field with value `{val}` " "is not valid because:", ) ) cudaDeviceCountMin = None if "cudaDeviceCountMin" in _doc: try: cudaDeviceCountMin = load_field( _doc.get("cudaDeviceCountMin"), union_of_None_type_or_inttype_or_ExpressionLoader, baseuri, loadingOptions, lc=_doc.get("cudaDeviceCountMin") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `cudaDeviceCountMin`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("cudaDeviceCountMin") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `cudaDeviceCountMin` field is not valid because:", SourceLine(_doc, "cudaDeviceCountMin", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `cudaDeviceCountMin` field is not valid because:", SourceLine(_doc, "cudaDeviceCountMin", str), [e], detailed_message=f"the `cudaDeviceCountMin` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("cudaVersionMin") is None: raise ValidationException("missing required field `cudaVersionMin`", None, []) cudaVersionMin = load_field( _doc.get("cudaVersionMin"), strtype, baseuri, loadingOptions, lc=_doc.get("cudaVersionMin") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `cudaVersionMin`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("cudaVersionMin") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `cudaVersionMin` field is not valid because:", SourceLine(_doc, "cudaVersionMin", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `cudaVersionMin` field is not valid because:", SourceLine(_doc, "cudaVersionMin", str), [e], detailed_message=f"the `cudaVersionMin` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `class`, `cudaComputeCapability`, `cudaDeviceCountMax`, `cudaDeviceCountMin`, `cudaVersionMin`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( cudaComputeCapability=cudaComputeCapability, cudaDeviceCountMax=cudaDeviceCountMax, cudaDeviceCountMin=cudaDeviceCountMin, cudaVersionMin=cudaVersionMin, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.class_ is not None: uri = self.loadingOptions.vocab[self.class_] if p := self.loadingOptions.rvocab.get(uri[: -len(self.class_)]): uri = f"{p}:{self.class_}" else: uri = self.class_ u = save_relative_uri(uri, base_url, False, None, relative_uris) r["class"] = u if self.cudaComputeCapability is not None: r["cudaComputeCapability"] = save( self.cudaComputeCapability, top=False, base_url=base_url, relative_uris=relative_uris, ) if self.cudaDeviceCountMax is not None: r["cudaDeviceCountMax"] = save( self.cudaDeviceCountMax, top=False, base_url=base_url, relative_uris=relative_uris, ) if self.cudaDeviceCountMin is not None: r["cudaDeviceCountMin"] = save( self.cudaDeviceCountMin, top=False, base_url=base_url, relative_uris=relative_uris, ) if self.cudaVersionMin is not None: r["cudaVersionMin"] = save( self.cudaVersionMin, top=False, base_url=base_url, relative_uris=relative_uris, ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset( [ "class", "cudaComputeCapability", "cudaDeviceCountMax", "cudaDeviceCountMin", "cudaVersionMin", ] ) class LoopInput(Saveable): id: str def __init__( self, default: Optional[Any] = None, id: Optional[Any] = None, linkMerge: Optional[Any] = None, loopSource: Optional[Any] = None, pickValue: Optional[Any] = None, valueFrom: Optional[Any] = None, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.default = default self.id = id if id is not None else "_:" + str(_uuid__.uuid4()) self.linkMerge = linkMerge self.loopSource = loopSource self.pickValue = pickValue self.valueFrom = valueFrom def __eq__(self, other: Any) -> bool: if isinstance(other, LoopInput): return bool( self.default == other.default and self.id == other.id and self.linkMerge == other.linkMerge and self.loopSource == other.loopSource and self.pickValue == other.pickValue and self.valueFrom == other.valueFrom ) return False def __hash__(self) -> int: return hash( ( self.default, self.id, self.linkMerge, self.loopSource, self.pickValue, self.valueFrom, ) ) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "LoopInput": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] id = None if "id" in _doc: try: id = load_field( _doc.get("id"), uri_union_of_None_type_or_strtype_True_False_None_None, baseuri, loadingOptions, lc=_doc.get("id") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `id`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("id") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `id` field is not valid because:", SourceLine(_doc, "id", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `id` field is not valid because:", SourceLine(_doc, "id", str), [e], detailed_message=f"the `id` field with value `{val}` " "is not valid because:", ) ) __original_id_is_none = id is None if id is None: if docRoot is not None: id = docRoot else: id = "_:" + str(_uuid__.uuid4()) if not __original_id_is_none: baseuri = cast(str, id) default = None if "default" in _doc: try: default = load_field( _doc.get("default"), union_of_None_type_or_Any_type, baseuri, loadingOptions, lc=_doc.get("default") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `default`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("default") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `default` field is not valid because:", SourceLine(_doc, "default", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `default` field is not valid because:", SourceLine(_doc, "default", str), [e], detailed_message=f"the `default` field with value `{val}` " "is not valid because:", ) ) linkMerge = None if "linkMerge" in _doc: try: linkMerge = load_field( _doc.get("linkMerge"), union_of_None_type_or_LinkMergeMethodLoader, baseuri, loadingOptions, lc=_doc.get("linkMerge") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `linkMerge`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("linkMerge") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `linkMerge` field is not valid because:", SourceLine(_doc, "linkMerge", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `linkMerge` field is not valid because:", SourceLine(_doc, "linkMerge", str), [e], detailed_message=f"the `linkMerge` field with value `{val}` " "is not valid because:", ) ) loopSource = None if "loopSource" in _doc: try: loopSource = load_field( _doc.get("loopSource"), uri_union_of_None_type_or_strtype_or_array_of_strtype_False_False_1_None, baseuri, loadingOptions, lc=_doc.get("loopSource") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `loopSource`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("loopSource") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `loopSource` field is not valid because:", SourceLine(_doc, "loopSource", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `loopSource` field is not valid because:", SourceLine(_doc, "loopSource", str), [e], detailed_message=f"the `loopSource` field with value `{val}` " "is not valid because:", ) ) pickValue = None if "pickValue" in _doc: try: pickValue = load_field( _doc.get("pickValue"), union_of_None_type_or_PickValueMethodLoader, baseuri, loadingOptions, lc=_doc.get("pickValue") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `pickValue`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("pickValue") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `pickValue` field is not valid because:", SourceLine(_doc, "pickValue", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `pickValue` field is not valid because:", SourceLine(_doc, "pickValue", str), [e], detailed_message=f"the `pickValue` field with value `{val}` " "is not valid because:", ) ) valueFrom = None if "valueFrom" in _doc: try: valueFrom = load_field( _doc.get("valueFrom"), union_of_None_type_or_strtype_or_ExpressionLoader, baseuri, loadingOptions, lc=_doc.get("valueFrom") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `valueFrom`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("valueFrom") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `valueFrom` field is not valid because:", SourceLine(_doc, "valueFrom", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `valueFrom` field is not valid because:", SourceLine(_doc, "valueFrom", str), [e], detailed_message=f"the `valueFrom` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `default`, `id`, `linkMerge`, `loopSource`, `pickValue`, `valueFrom`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( default=default, id=id, linkMerge=linkMerge, loopSource=loopSource, pickValue=pickValue, valueFrom=valueFrom, extension_fields=extension_fields, loadingOptions=loadingOptions, ) loadingOptions.idx[cast(str, id)] = (_constructed, loadingOptions) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.id is not None: u = save_relative_uri(self.id, base_url, True, None, relative_uris) r["id"] = u if self.default is not None: r["default"] = save( self.default, top=False, base_url=self.id, relative_uris=relative_uris ) if self.linkMerge is not None: r["linkMerge"] = save( self.linkMerge, top=False, base_url=self.id, relative_uris=relative_uris ) if self.loopSource is not None: u = save_relative_uri(self.loopSource, self.id, False, 1, relative_uris) r["loopSource"] = u if self.pickValue is not None: r["pickValue"] = save( self.pickValue, top=False, base_url=self.id, relative_uris=relative_uris ) if self.valueFrom is not None: r["valueFrom"] = save( self.valueFrom, top=False, base_url=self.id, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset( ["default", "id", "linkMerge", "loopSource", "pickValue", "valueFrom"] ) class Loop(ProcessRequirement): """ Prototype to enable workflow-level looping of a step. Valid only under `requirements` of a https://www.commonwl.org/v1.2/Workflow.html#WorkflowStep. Unlike other CWL requirements, Loop requirement is not propagated to inner steps. `loopWhen` is an expansion of the CWL v1.2 `when` construct which controls conditional execution. Using `loopWhen` and `when` for the same step will produce an error. `loopWhen` is not compatible with `scatter` at this time and combining the two in the same step will produce an error. """ def __init__( self, loop: Any, loopWhen: Any, outputMethod: Any, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.class_ = "Loop" self.loop = loop self.loopWhen = loopWhen self.outputMethod = outputMethod def __eq__(self, other: Any) -> bool: if isinstance(other, Loop): return bool( self.class_ == other.class_ and self.loop == other.loop and self.loopWhen == other.loopWhen and self.outputMethod == other.outputMethod ) return False def __hash__(self) -> int: return hash((self.class_, self.loop, self.loopWhen, self.outputMethod)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "Loop": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("class") is None: raise ValidationException("missing required field `class`", None, []) class_ = load_field( _doc.get("class"), uri_strtype_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("class") ) if class_ not in (cls.__name__, loadingOptions.vocab.get(cls.__name__)): raise ValidationException(f"tried `{cls.__name__}` but") except ValidationException as e: raise e try: if _doc.get("loop") is None: raise ValidationException("missing required field `loop`", None, []) loop = load_field( _doc.get("loop"), idmap_loop_array_of_LoopInputLoader, baseuri, loadingOptions, lc=_doc.get("loop") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `loop`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("loop") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `loop` field is not valid because:", SourceLine(_doc, "loop", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `loop` field is not valid because:", SourceLine(_doc, "loop", str), [e], detailed_message=f"the `loop` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("loopWhen") is None: raise ValidationException("missing required field `loopWhen`", None, []) loopWhen = load_field( _doc.get("loopWhen"), ExpressionLoader, baseuri, loadingOptions, lc=_doc.get("loopWhen") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `loopWhen`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("loopWhen") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `loopWhen` field is not valid because:", SourceLine(_doc, "loopWhen", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `loopWhen` field is not valid because:", SourceLine(_doc, "loopWhen", str), [e], detailed_message=f"the `loopWhen` field with value `{val}` " "is not valid because:", ) ) try: if _doc.get("outputMethod") is None: raise ValidationException("missing required field `outputMethod`", None, []) outputMethod = load_field( _doc.get("outputMethod"), LoopOutputModesLoader, baseuri, loadingOptions, lc=_doc.get("outputMethod") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `outputMethod`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("outputMethod") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `outputMethod` field is not valid because:", SourceLine(_doc, "outputMethod", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `outputMethod` field is not valid because:", SourceLine(_doc, "outputMethod", str), [e], detailed_message=f"the `outputMethod` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `class`, `loop`, `loopWhen`, `outputMethod`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( loop=loop, loopWhen=loopWhen, outputMethod=outputMethod, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.class_ is not None: uri = self.loadingOptions.vocab[self.class_] if p := self.loadingOptions.rvocab.get(uri[: -len(self.class_)]): uri = f"{p}:{self.class_}" else: uri = self.class_ u = save_relative_uri(uri, base_url, False, None, relative_uris) r["class"] = u if self.loop is not None: r["loop"] = save( self.loop, top=False, base_url=base_url, relative_uris=relative_uris ) if self.loopWhen is not None: r["loopWhen"] = save( self.loopWhen, top=False, base_url=base_url, relative_uris=relative_uris ) if self.outputMethod is not None: r["outputMethod"] = save( self.outputMethod, top=False, base_url=base_url, relative_uris=relative_uris, ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["class", "loop", "loopWhen", "outputMethod"]) class ShmSize(ProcessRequirement): def __init__( self, shmSize: Any, extension_fields: Optional[dict[str, Any]] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> None: if extension_fields: self.extension_fields = extension_fields else: self.extension_fields = CommentedMap() if loadingOptions: self.loadingOptions = loadingOptions else: self.loadingOptions = LoadingOptions() self.class_ = "ShmSize" self.shmSize = shmSize def __eq__(self, other: Any) -> bool: if isinstance(other, ShmSize): return bool(self.class_ == other.class_ and self.shmSize == other.shmSize) return False def __hash__(self) -> int: return hash((self.class_, self.shmSize)) @classmethod def fromDoc( cls, doc: Any, baseuri: str, loadingOptions: LoadingOptions, docRoot: Optional[str] = None ) -> "ShmSize": _doc = copy.copy(doc) if hasattr(doc, "lc"): _doc.lc.data = doc.lc.data _doc.lc.filename = doc.lc.filename _errors__ = [] try: if _doc.get("class") is None: raise ValidationException("missing required field `class`", None, []) class_ = load_field( _doc.get("class"), uri_strtype_False_True_None_None, baseuri, loadingOptions, lc=_doc.get("class") ) if class_ not in (cls.__name__, loadingOptions.vocab.get(cls.__name__)): raise ValidationException(f"tried `{cls.__name__}` but") except ValidationException as e: raise e try: if _doc.get("shmSize") is None: raise ValidationException("missing required field `shmSize`", None, []) shmSize = load_field( _doc.get("shmSize"), strtype, baseuri, loadingOptions, lc=_doc.get("shmSize") ) except ValidationException as e: error_message, to_print, verb_tensage = parse_errors(str(e)) if str(e) == "missing required field `shmSize`": _errors__.append( ValidationException( str(e), None ) ) else: val = _doc.get("shmSize") if error_message != str(e): val_type = convert_typing(extract_type(type(val))) _errors__.append( ValidationException( "the `shmSize` field is not valid because:", SourceLine(_doc, "shmSize", str), [ValidationException(f"Value is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}", detailed_message=f"Value `{val}` is a {val_type}, " f"but valid {to_print} for this field " f"{verb_tensage} {error_message}")], ) ) else: _errors__.append( ValidationException( "the `shmSize` field is not valid because:", SourceLine(_doc, "shmSize", str), [e], detailed_message=f"the `shmSize` field with value `{val}` " "is not valid because:", ) ) extension_fields: dict[str, Any] = {} for k in _doc.keys(): if k not in cls.attrs: if not k: _errors__.append( ValidationException("mapping with implicit null key") ) elif ":" in k: ex = expand_url( k, "", loadingOptions, scoped_id=False, vocab_term=False ) extension_fields[ex] = _doc[k] else: _errors__.append( ValidationException( "invalid field `{}`, expected one of: `class`, `shmSize`".format( k ), SourceLine(_doc, k, str), ) ) if _errors__: raise ValidationException("", None, _errors__, "*") _constructed = cls( shmSize=shmSize, extension_fields=extension_fields, loadingOptions=loadingOptions, ) return _constructed def save( self, top: bool = False, base_url: str = "", relative_uris: bool = True ) -> dict[str, Any]: r: dict[str, Any] = {} if relative_uris: for ef in self.extension_fields: r[prefix_url(ef, self.loadingOptions.vocab)] = self.extension_fields[ef] else: for ef in self.extension_fields: r[ef] = self.extension_fields[ef] if self.class_ is not None: uri = self.loadingOptions.vocab[self.class_] if p := self.loadingOptions.rvocab.get(uri[: -len(self.class_)]): uri = f"{p}:{self.class_}" else: uri = self.class_ u = save_relative_uri(uri, base_url, False, None, relative_uris) r["class"] = u if self.shmSize is not None: r["shmSize"] = save( self.shmSize, top=False, base_url=base_url, relative_uris=relative_uris ) # top refers to the directory level if top: if self.loadingOptions.namespaces: r["$namespaces"] = self.loadingOptions.namespaces if self.loadingOptions.schemas: r["$schemas"] = self.loadingOptions.schemas return r attrs = frozenset(["class", "shmSize"]) _vocab = { "Any": "https://w3id.org/cwl/salad#Any", "ArraySchema": "https://w3id.org/cwl/salad#ArraySchema", "CUDARequirement": "http://commonwl.org/cwltool#CUDARequirement", "CWLArraySchema": "https://w3id.org/cwl/cwl#CWLArraySchema", "CWLInputFile": "https://w3id.org/cwl/cwl#CWLInputFile", "CWLObjectType": "https://w3id.org/cwl/cwl#CWLObjectType", "CWLRecordField": "https://w3id.org/cwl/cwl#CWLRecordField", "CWLRecordSchema": "https://w3id.org/cwl/cwl#CWLRecordSchema", "CWLType": "https://w3id.org/cwl/cwl#CWLType", "CWLVersion": "https://w3id.org/cwl/cwl#CWLVersion", "CommandInputArraySchema": "https://w3id.org/cwl/cwl#CommandInputArraySchema", "CommandInputEnumSchema": "https://w3id.org/cwl/cwl#CommandInputEnumSchema", "CommandInputParameter": "https://w3id.org/cwl/cwl#CommandInputParameter", "CommandInputRecordField": "https://w3id.org/cwl/cwl#CommandInputRecordField", "CommandInputRecordSchema": "https://w3id.org/cwl/cwl#CommandInputRecordSchema", "CommandInputSchema": "https://w3id.org/cwl/cwl#CommandInputSchema", "CommandLineBindable": "https://w3id.org/cwl/cwl#CommandLineBindable", "CommandLineBinding": "https://w3id.org/cwl/cwl#CommandLineBinding", "CommandLineTool": "https://w3id.org/cwl/cwl#CommandLineTool", "CommandOutputArraySchema": "https://w3id.org/cwl/cwl#CommandOutputArraySchema", "CommandOutputBinding": "https://w3id.org/cwl/cwl#CommandOutputBinding", "CommandOutputEnumSchema": "https://w3id.org/cwl/cwl#CommandOutputEnumSchema", "CommandOutputParameter": "https://w3id.org/cwl/cwl#CommandOutputParameter", "CommandOutputRecordField": "https://w3id.org/cwl/cwl#CommandOutputRecordField", "CommandOutputRecordSchema": "https://w3id.org/cwl/cwl#CommandOutputRecordSchema", "Directory": "https://w3id.org/cwl/cwl#Directory", "Dirent": "https://w3id.org/cwl/cwl#Dirent", "DockerRequirement": "https://w3id.org/cwl/cwl#DockerRequirement", "Documented": "https://w3id.org/cwl/salad#Documented", "EnumSchema": "https://w3id.org/cwl/salad#EnumSchema", "EnvVarRequirement": "https://w3id.org/cwl/cwl#EnvVarRequirement", "EnvironmentDef": "https://w3id.org/cwl/cwl#EnvironmentDef", "Expression": "https://w3id.org/cwl/cwl#Expression", "ExpressionPlaceholder": "https://w3id.org/cwl/cwl#ExpressionPlaceholder", "ExpressionTool": "https://w3id.org/cwl/cwl#ExpressionTool", "ExpressionToolOutputParameter": "https://w3id.org/cwl/cwl#ExpressionToolOutputParameter", "FieldBase": "https://w3id.org/cwl/cwl#FieldBase", "File": "https://w3id.org/cwl/cwl#File", "IOSchema": "https://w3id.org/cwl/cwl#IOSchema", "Identified": "https://w3id.org/cwl/cwl#Identified", "IdentifierRequired": "https://w3id.org/cwl/cwl#IdentifierRequired", "InitialWorkDirRequirement": "https://w3id.org/cwl/cwl#InitialWorkDirRequirement", "InlineJavascriptRequirement": "https://w3id.org/cwl/cwl#InlineJavascriptRequirement", "InplaceUpdateRequirement": "https://w3id.org/cwl/cwl#InplaceUpdateRequirement", "InputArraySchema": "https://w3id.org/cwl/cwl#InputArraySchema", "InputBinding": "https://w3id.org/cwl/cwl#InputBinding", "InputEnumSchema": "https://w3id.org/cwl/cwl#InputEnumSchema", "InputFormat": "https://w3id.org/cwl/cwl#InputFormat", "InputParameter": "https://w3id.org/cwl/cwl#InputParameter", "InputRecordField": "https://w3id.org/cwl/cwl#InputRecordField", "InputRecordSchema": "https://w3id.org/cwl/cwl#InputRecordSchema", "InputSchema": "https://w3id.org/cwl/cwl#InputSchema", "Labeled": "https://w3id.org/cwl/cwl#Labeled", "LinkMergeMethod": "https://w3id.org/cwl/cwl#LinkMergeMethod", "LoadContents": "https://w3id.org/cwl/cwl#LoadContents", "LoadListingEnum": "https://w3id.org/cwl/cwl#LoadListingEnum", "LoadListingRequirement": "https://w3id.org/cwl/cwl#LoadListingRequirement", "Loop": "http://commonwl.org/cwltool#Loop", "LoopInput": "http://commonwl.org/cwltool#LoopInput", "MPIRequirement": "http://commonwl.org/cwltool#MPIRequirement", "MapSchema": "https://w3id.org/cwl/salad#MapSchema", "MultipleInputFeatureRequirement": "https://w3id.org/cwl/cwl#MultipleInputFeatureRequirement", "NetworkAccess": "https://w3id.org/cwl/cwl#NetworkAccess", "Operation": "https://w3id.org/cwl/cwl#Operation", "OperationInputParameter": "https://w3id.org/cwl/cwl#OperationInputParameter", "OperationOutputParameter": "https://w3id.org/cwl/cwl#OperationOutputParameter", "OutputArraySchema": "https://w3id.org/cwl/cwl#OutputArraySchema", "OutputEnumSchema": "https://w3id.org/cwl/cwl#OutputEnumSchema", "OutputFormat": "https://w3id.org/cwl/cwl#OutputFormat", "OutputParameter": "https://w3id.org/cwl/cwl#OutputParameter", "OutputRecordField": "https://w3id.org/cwl/cwl#OutputRecordField", "OutputRecordSchema": "https://w3id.org/cwl/cwl#OutputRecordSchema", "OutputSchema": "https://w3id.org/cwl/cwl#OutputSchema", "Parameter": "https://w3id.org/cwl/cwl#Parameter", "PickValueMethod": "https://w3id.org/cwl/cwl#PickValueMethod", "PrimitiveType": "https://w3id.org/cwl/salad#PrimitiveType", "Process": "https://w3id.org/cwl/cwl#Process", "ProcessGenerator": "http://commonwl.org/cwltool#ProcessGenerator", "ProcessRequirement": "https://w3id.org/cwl/cwl#ProcessRequirement", "RecordField": "https://w3id.org/cwl/salad#RecordField", "RecordSchema": "https://w3id.org/cwl/salad#RecordSchema", "ResourceRequirement": "https://w3id.org/cwl/cwl#ResourceRequirement", "ScatterFeatureRequirement": "https://w3id.org/cwl/cwl#ScatterFeatureRequirement", "ScatterMethod": "https://w3id.org/cwl/cwl#ScatterMethod", "SchemaDefRequirement": "https://w3id.org/cwl/cwl#SchemaDefRequirement", "SecondaryFileSchema": "https://w3id.org/cwl/cwl#SecondaryFileSchema", "Secrets": "http://commonwl.org/cwltool#Secrets", "ShellCommandRequirement": "https://w3id.org/cwl/cwl#ShellCommandRequirement", "ShmSize": "http://commonwl.org/cwltool#ShmSize", "Sink": "https://w3id.org/cwl/cwl#Sink", "SoftwarePackage": "https://w3id.org/cwl/cwl#SoftwarePackage", "SoftwareRequirement": "https://w3id.org/cwl/cwl#SoftwareRequirement", "StepInputExpressionRequirement": "https://w3id.org/cwl/cwl#StepInputExpressionRequirement", "SubworkflowFeatureRequirement": "https://w3id.org/cwl/cwl#SubworkflowFeatureRequirement", "ToolTimeLimit": "https://w3id.org/cwl/cwl#ToolTimeLimit", "UnionSchema": "https://w3id.org/cwl/salad#UnionSchema", "WorkReuse": "https://w3id.org/cwl/cwl#WorkReuse", "Workflow": "https://w3id.org/cwl/cwl#Workflow", "WorkflowInputParameter": "https://w3id.org/cwl/cwl#WorkflowInputParameter", "WorkflowOutputParameter": "https://w3id.org/cwl/cwl#WorkflowOutputParameter", "WorkflowStep": "https://w3id.org/cwl/cwl#WorkflowStep", "WorkflowStepInput": "https://w3id.org/cwl/cwl#WorkflowStepInput", "WorkflowStepOutput": "https://w3id.org/cwl/cwl#WorkflowStepOutput", "all": "http://commonwl.org/cwltool#Loop/outputMethod/LoopOutputModes/all", "all_non_null": "https://w3id.org/cwl/cwl#PickValueMethod/all_non_null", "array": "https://w3id.org/cwl/salad#array", "boolean": "http://www.w3.org/2001/XMLSchema#boolean", "deep_listing": "https://w3id.org/cwl/cwl#LoadListingEnum/deep_listing", "dotproduct": "https://w3id.org/cwl/cwl#ScatterMethod/dotproduct", "double": "http://www.w3.org/2001/XMLSchema#double", "draft-2": "https://w3id.org/cwl/cwl#draft-2", "draft-3": "https://w3id.org/cwl/cwl#draft-3", "draft-3.dev1": "https://w3id.org/cwl/cwl#draft-3.dev1", "draft-3.dev2": "https://w3id.org/cwl/cwl#draft-3.dev2", "draft-3.dev3": "https://w3id.org/cwl/cwl#draft-3.dev3", "draft-3.dev4": "https://w3id.org/cwl/cwl#draft-3.dev4", "draft-3.dev5": "https://w3id.org/cwl/cwl#draft-3.dev5", "draft-4.dev1": "https://w3id.org/cwl/cwl#draft-4.dev1", "draft-4.dev2": "https://w3id.org/cwl/cwl#draft-4.dev2", "draft-4.dev3": "https://w3id.org/cwl/cwl#draft-4.dev3", "enum": "https://w3id.org/cwl/salad#enum", "first_non_null": "https://w3id.org/cwl/cwl#PickValueMethod/first_non_null", "flat_crossproduct": "https://w3id.org/cwl/cwl#ScatterMethod/flat_crossproduct", "float": "http://www.w3.org/2001/XMLSchema#float", "int": "http://www.w3.org/2001/XMLSchema#int", "last": "http://commonwl.org/cwltool#Loop/outputMethod/LoopOutputModes/last", "long": "http://www.w3.org/2001/XMLSchema#long", "map": "https://w3id.org/cwl/salad#map", "merge_flattened": "https://w3id.org/cwl/cwl#LinkMergeMethod/merge_flattened", "merge_nested": "https://w3id.org/cwl/cwl#LinkMergeMethod/merge_nested", "nested_crossproduct": "https://w3id.org/cwl/cwl#ScatterMethod/nested_crossproduct", "no_listing": "https://w3id.org/cwl/cwl#LoadListingEnum/no_listing", "null": "https://w3id.org/cwl/salad#null", "record": "https://w3id.org/cwl/salad#record", "shallow_listing": "https://w3id.org/cwl/cwl#LoadListingEnum/shallow_listing", "stderr": "https://w3id.org/cwl/cwl#stderr", "stdin": "https://w3id.org/cwl/cwl#stdin", "stdout": "https://w3id.org/cwl/cwl#stdout", "string": "http://www.w3.org/2001/XMLSchema#string", "the_only_non_null": "https://w3id.org/cwl/cwl#PickValueMethod/the_only_non_null", "union": "https://w3id.org/cwl/salad#union", "v1.0": "https://w3id.org/cwl/cwl#v1.0", "v1.0.dev4": "https://w3id.org/cwl/cwl#v1.0.dev4", "v1.1": "https://w3id.org/cwl/cwl#v1.1", "v1.1.0-dev1": "https://w3id.org/cwl/cwl#v1.1.0-dev1", "v1.2": "https://w3id.org/cwl/cwl#v1.2", "v1.2.0-dev1": "https://w3id.org/cwl/cwl#v1.2.0-dev1", "v1.2.0-dev2": "https://w3id.org/cwl/cwl#v1.2.0-dev2", "v1.2.0-dev3": "https://w3id.org/cwl/cwl#v1.2.0-dev3", "v1.2.0-dev4": "https://w3id.org/cwl/cwl#v1.2.0-dev4", "v1.2.0-dev5": "https://w3id.org/cwl/cwl#v1.2.0-dev5", } _rvocab = { "https://w3id.org/cwl/salad#Any": "Any", "https://w3id.org/cwl/salad#ArraySchema": "ArraySchema", "http://commonwl.org/cwltool#CUDARequirement": "CUDARequirement", "https://w3id.org/cwl/cwl#CWLArraySchema": "CWLArraySchema", "https://w3id.org/cwl/cwl#CWLInputFile": "CWLInputFile", "https://w3id.org/cwl/cwl#CWLObjectType": "CWLObjectType", "https://w3id.org/cwl/cwl#CWLRecordField": "CWLRecordField", "https://w3id.org/cwl/cwl#CWLRecordSchema": "CWLRecordSchema", "https://w3id.org/cwl/cwl#CWLType": "CWLType", "https://w3id.org/cwl/cwl#CWLVersion": "CWLVersion", "https://w3id.org/cwl/cwl#CommandInputArraySchema": "CommandInputArraySchema", "https://w3id.org/cwl/cwl#CommandInputEnumSchema": "CommandInputEnumSchema", "https://w3id.org/cwl/cwl#CommandInputParameter": "CommandInputParameter", "https://w3id.org/cwl/cwl#CommandInputRecordField": "CommandInputRecordField", "https://w3id.org/cwl/cwl#CommandInputRecordSchema": "CommandInputRecordSchema", "https://w3id.org/cwl/cwl#CommandInputSchema": "CommandInputSchema", "https://w3id.org/cwl/cwl#CommandLineBindable": "CommandLineBindable", "https://w3id.org/cwl/cwl#CommandLineBinding": "CommandLineBinding", "https://w3id.org/cwl/cwl#CommandLineTool": "CommandLineTool", "https://w3id.org/cwl/cwl#CommandOutputArraySchema": "CommandOutputArraySchema", "https://w3id.org/cwl/cwl#CommandOutputBinding": "CommandOutputBinding", "https://w3id.org/cwl/cwl#CommandOutputEnumSchema": "CommandOutputEnumSchema", "https://w3id.org/cwl/cwl#CommandOutputParameter": "CommandOutputParameter", "https://w3id.org/cwl/cwl#CommandOutputRecordField": "CommandOutputRecordField", "https://w3id.org/cwl/cwl#CommandOutputRecordSchema": "CommandOutputRecordSchema", "https://w3id.org/cwl/cwl#Directory": "Directory", "https://w3id.org/cwl/cwl#Dirent": "Dirent", "https://w3id.org/cwl/cwl#DockerRequirement": "DockerRequirement", "https://w3id.org/cwl/salad#Documented": "Documented", "https://w3id.org/cwl/salad#EnumSchema": "EnumSchema", "https://w3id.org/cwl/cwl#EnvVarRequirement": "EnvVarRequirement", "https://w3id.org/cwl/cwl#EnvironmentDef": "EnvironmentDef", "https://w3id.org/cwl/cwl#Expression": "Expression", "https://w3id.org/cwl/cwl#ExpressionPlaceholder": "ExpressionPlaceholder", "https://w3id.org/cwl/cwl#ExpressionTool": "ExpressionTool", "https://w3id.org/cwl/cwl#ExpressionToolOutputParameter": "ExpressionToolOutputParameter", "https://w3id.org/cwl/cwl#FieldBase": "FieldBase", "https://w3id.org/cwl/cwl#File": "File", "https://w3id.org/cwl/cwl#IOSchema": "IOSchema", "https://w3id.org/cwl/cwl#Identified": "Identified", "https://w3id.org/cwl/cwl#IdentifierRequired": "IdentifierRequired", "https://w3id.org/cwl/cwl#InitialWorkDirRequirement": "InitialWorkDirRequirement", "https://w3id.org/cwl/cwl#InlineJavascriptRequirement": "InlineJavascriptRequirement", "https://w3id.org/cwl/cwl#InplaceUpdateRequirement": "InplaceUpdateRequirement", "https://w3id.org/cwl/cwl#InputArraySchema": "InputArraySchema", "https://w3id.org/cwl/cwl#InputBinding": "InputBinding", "https://w3id.org/cwl/cwl#InputEnumSchema": "InputEnumSchema", "https://w3id.org/cwl/cwl#InputFormat": "InputFormat", "https://w3id.org/cwl/cwl#InputParameter": "InputParameter", "https://w3id.org/cwl/cwl#InputRecordField": "InputRecordField", "https://w3id.org/cwl/cwl#InputRecordSchema": "InputRecordSchema", "https://w3id.org/cwl/cwl#InputSchema": "InputSchema", "https://w3id.org/cwl/cwl#Labeled": "Labeled", "https://w3id.org/cwl/cwl#LinkMergeMethod": "LinkMergeMethod", "https://w3id.org/cwl/cwl#LoadContents": "LoadContents", "https://w3id.org/cwl/cwl#LoadListingEnum": "LoadListingEnum", "https://w3id.org/cwl/cwl#LoadListingRequirement": "LoadListingRequirement", "http://commonwl.org/cwltool#Loop": "Loop", "http://commonwl.org/cwltool#LoopInput": "LoopInput", "http://commonwl.org/cwltool#MPIRequirement": "MPIRequirement", "https://w3id.org/cwl/salad#MapSchema": "MapSchema", "https://w3id.org/cwl/cwl#MultipleInputFeatureRequirement": "MultipleInputFeatureRequirement", "https://w3id.org/cwl/cwl#NetworkAccess": "NetworkAccess", "https://w3id.org/cwl/cwl#Operation": "Operation", "https://w3id.org/cwl/cwl#OperationInputParameter": "OperationInputParameter", "https://w3id.org/cwl/cwl#OperationOutputParameter": "OperationOutputParameter", "https://w3id.org/cwl/cwl#OutputArraySchema": "OutputArraySchema", "https://w3id.org/cwl/cwl#OutputEnumSchema": "OutputEnumSchema", "https://w3id.org/cwl/cwl#OutputFormat": "OutputFormat", "https://w3id.org/cwl/cwl#OutputParameter": "OutputParameter", "https://w3id.org/cwl/cwl#OutputRecordField": "OutputRecordField", "https://w3id.org/cwl/cwl#OutputRecordSchema": "OutputRecordSchema", "https://w3id.org/cwl/cwl#OutputSchema": "OutputSchema", "https://w3id.org/cwl/cwl#Parameter": "Parameter", "https://w3id.org/cwl/cwl#PickValueMethod": "PickValueMethod", "https://w3id.org/cwl/salad#PrimitiveType": "PrimitiveType", "https://w3id.org/cwl/cwl#Process": "Process", "http://commonwl.org/cwltool#ProcessGenerator": "ProcessGenerator", "https://w3id.org/cwl/cwl#ProcessRequirement": "ProcessRequirement", "https://w3id.org/cwl/salad#RecordField": "RecordField", "https://w3id.org/cwl/salad#RecordSchema": "RecordSchema", "https://w3id.org/cwl/cwl#ResourceRequirement": "ResourceRequirement", "https://w3id.org/cwl/cwl#ScatterFeatureRequirement": "ScatterFeatureRequirement", "https://w3id.org/cwl/cwl#ScatterMethod": "ScatterMethod", "https://w3id.org/cwl/cwl#SchemaDefRequirement": "SchemaDefRequirement", "https://w3id.org/cwl/cwl#SecondaryFileSchema": "SecondaryFileSchema", "http://commonwl.org/cwltool#Secrets": "Secrets", "https://w3id.org/cwl/cwl#ShellCommandRequirement": "ShellCommandRequirement", "http://commonwl.org/cwltool#ShmSize": "ShmSize", "https://w3id.org/cwl/cwl#Sink": "Sink", "https://w3id.org/cwl/cwl#SoftwarePackage": "SoftwarePackage", "https://w3id.org/cwl/cwl#SoftwareRequirement": "SoftwareRequirement", "https://w3id.org/cwl/cwl#StepInputExpressionRequirement": "StepInputExpressionRequirement", "https://w3id.org/cwl/cwl#SubworkflowFeatureRequirement": "SubworkflowFeatureRequirement", "https://w3id.org/cwl/cwl#ToolTimeLimit": "ToolTimeLimit", "https://w3id.org/cwl/salad#UnionSchema": "UnionSchema", "https://w3id.org/cwl/cwl#WorkReuse": "WorkReuse", "https://w3id.org/cwl/cwl#Workflow": "Workflow", "https://w3id.org/cwl/cwl#WorkflowInputParameter": "WorkflowInputParameter", "https://w3id.org/cwl/cwl#WorkflowOutputParameter": "WorkflowOutputParameter", "https://w3id.org/cwl/cwl#WorkflowStep": "WorkflowStep", "https://w3id.org/cwl/cwl#WorkflowStepInput": "WorkflowStepInput", "https://w3id.org/cwl/cwl#WorkflowStepOutput": "WorkflowStepOutput", "http://commonwl.org/cwltool#Loop/outputMethod/LoopOutputModes/all": "all", "https://w3id.org/cwl/cwl#PickValueMethod/all_non_null": "all_non_null", "https://w3id.org/cwl/salad#array": "array", "http://www.w3.org/2001/XMLSchema#boolean": "boolean", "https://w3id.org/cwl/cwl#LoadListingEnum/deep_listing": "deep_listing", "https://w3id.org/cwl/cwl#ScatterMethod/dotproduct": "dotproduct", "http://www.w3.org/2001/XMLSchema#double": "double", "https://w3id.org/cwl/cwl#draft-2": "draft-2", "https://w3id.org/cwl/cwl#draft-3": "draft-3", "https://w3id.org/cwl/cwl#draft-3.dev1": "draft-3.dev1", "https://w3id.org/cwl/cwl#draft-3.dev2": "draft-3.dev2", "https://w3id.org/cwl/cwl#draft-3.dev3": "draft-3.dev3", "https://w3id.org/cwl/cwl#draft-3.dev4": "draft-3.dev4", "https://w3id.org/cwl/cwl#draft-3.dev5": "draft-3.dev5", "https://w3id.org/cwl/cwl#draft-4.dev1": "draft-4.dev1", "https://w3id.org/cwl/cwl#draft-4.dev2": "draft-4.dev2", "https://w3id.org/cwl/cwl#draft-4.dev3": "draft-4.dev3", "https://w3id.org/cwl/salad#enum": "enum", "https://w3id.org/cwl/cwl#PickValueMethod/first_non_null": "first_non_null", "https://w3id.org/cwl/cwl#ScatterMethod/flat_crossproduct": "flat_crossproduct", "http://www.w3.org/2001/XMLSchema#float": "float", "http://www.w3.org/2001/XMLSchema#int": "int", "http://commonwl.org/cwltool#Loop/outputMethod/LoopOutputModes/last": "last", "http://www.w3.org/2001/XMLSchema#long": "long", "https://w3id.org/cwl/salad#map": "map", "https://w3id.org/cwl/cwl#LinkMergeMethod/merge_flattened": "merge_flattened", "https://w3id.org/cwl/cwl#LinkMergeMethod/merge_nested": "merge_nested", "https://w3id.org/cwl/cwl#ScatterMethod/nested_crossproduct": "nested_crossproduct", "https://w3id.org/cwl/cwl#LoadListingEnum/no_listing": "no_listing", "https://w3id.org/cwl/salad#null": "null", "https://w3id.org/cwl/salad#record": "record", "https://w3id.org/cwl/cwl#LoadListingEnum/shallow_listing": "shallow_listing", "https://w3id.org/cwl/cwl#stderr": "stderr", "https://w3id.org/cwl/cwl#stdin": "stdin", "https://w3id.org/cwl/cwl#stdout": "stdout", "http://www.w3.org/2001/XMLSchema#string": "string", "https://w3id.org/cwl/cwl#PickValueMethod/the_only_non_null": "the_only_non_null", "https://w3id.org/cwl/salad#union": "union", "https://w3id.org/cwl/cwl#v1.0": "v1.0", "https://w3id.org/cwl/cwl#v1.0.dev4": "v1.0.dev4", "https://w3id.org/cwl/cwl#v1.1": "v1.1", "https://w3id.org/cwl/cwl#v1.1.0-dev1": "v1.1.0-dev1", "https://w3id.org/cwl/cwl#v1.2": "v1.2", "https://w3id.org/cwl/cwl#v1.2.0-dev1": "v1.2.0-dev1", "https://w3id.org/cwl/cwl#v1.2.0-dev2": "v1.2.0-dev2", "https://w3id.org/cwl/cwl#v1.2.0-dev3": "v1.2.0-dev3", "https://w3id.org/cwl/cwl#v1.2.0-dev4": "v1.2.0-dev4", "https://w3id.org/cwl/cwl#v1.2.0-dev5": "v1.2.0-dev5", } strtype = _PrimitiveLoader(str) inttype = _PrimitiveLoader(int) floattype = _PrimitiveLoader(float) booltype = _PrimitiveLoader(bool) None_type = _PrimitiveLoader(type(None)) Any_type = _AnyLoader() PrimitiveTypeLoader = _EnumLoader( ( "null", "boolean", "int", "long", "float", "double", "string", ), "PrimitiveType", ) """ Names of salad data types (based on Avro schema declarations). Refer to the [Avro schema declaration documentation](https://avro.apache.org/docs/current/spec.html#schemas) for detailed information. null: no value boolean: a binary value int: 32-bit signed integer long: 64-bit signed integer float: single precision (32-bit) IEEE 754 floating-point number double: double precision (64-bit) IEEE 754 floating-point number string: Unicode character sequence """ AnyLoader = _EnumLoader(("Any",), "Any") """ The **Any** type validates for any non-null value. """ RecordFieldLoader = _RecordLoader(RecordField, None, None) RecordSchemaLoader = _RecordLoader(RecordSchema, None, None) EnumSchemaLoader = _RecordLoader(EnumSchema, None, None) ArraySchemaLoader = _RecordLoader(ArraySchema, None, None) MapSchemaLoader = _RecordLoader(MapSchema, None, None) UnionSchemaLoader = _RecordLoader(UnionSchema, None, None) CWLTypeLoader = _EnumLoader( ( "null", "boolean", "int", "long", "float", "double", "string", "File", "Directory", ), "CWLType", ) """ Extends primitive types with the concept of a file and directory as a builtin type. File: A File object Directory: A Directory object """ CWLArraySchemaLoader = _RecordLoader(CWLArraySchema, None, None) CWLRecordFieldLoader = _RecordLoader(CWLRecordField, None, None) CWLRecordSchemaLoader = _RecordLoader(CWLRecordSchema, None, None) FileLoader = _RecordLoader(File, None, None) DirectoryLoader = _RecordLoader(Directory, None, None) CWLObjectTypeLoader = _UnionLoader((), "CWLObjectTypeLoader") union_of_None_type_or_CWLObjectTypeLoader = _UnionLoader( ( None_type, CWLObjectTypeLoader, ) ) array_of_union_of_None_type_or_CWLObjectTypeLoader = _ArrayLoader( union_of_None_type_or_CWLObjectTypeLoader ) map_of_union_of_None_type_or_CWLObjectTypeLoader = _MapLoader( union_of_None_type_or_CWLObjectTypeLoader, "None", None, None ) InlineJavascriptRequirementLoader = _RecordLoader( InlineJavascriptRequirement, None, None ) SchemaDefRequirementLoader = _RecordLoader(SchemaDefRequirement, None, None) LoadListingRequirementLoader = _RecordLoader(LoadListingRequirement, None, None) DockerRequirementLoader = _RecordLoader(DockerRequirement, None, None) SoftwareRequirementLoader = _RecordLoader(SoftwareRequirement, None, None) InitialWorkDirRequirementLoader = _RecordLoader(InitialWorkDirRequirement, None, None) EnvVarRequirementLoader = _RecordLoader(EnvVarRequirement, None, None) ShellCommandRequirementLoader = _RecordLoader(ShellCommandRequirement, None, None) ResourceRequirementLoader = _RecordLoader(ResourceRequirement, None, None) WorkReuseLoader = _RecordLoader(WorkReuse, None, None) NetworkAccessLoader = _RecordLoader(NetworkAccess, None, None) InplaceUpdateRequirementLoader = _RecordLoader(InplaceUpdateRequirement, None, None) ToolTimeLimitLoader = _RecordLoader(ToolTimeLimit, None, None) SubworkflowFeatureRequirementLoader = _RecordLoader( SubworkflowFeatureRequirement, None, None ) ScatterFeatureRequirementLoader = _RecordLoader(ScatterFeatureRequirement, None, None) MultipleInputFeatureRequirementLoader = _RecordLoader( MultipleInputFeatureRequirement, None, None ) StepInputExpressionRequirementLoader = _RecordLoader( StepInputExpressionRequirement, None, None ) SecretsLoader = _RecordLoader(Secrets, None, None) MPIRequirementLoader = _RecordLoader(MPIRequirement, None, None) CUDARequirementLoader = _RecordLoader(CUDARequirement, None, None) LoopLoader = _RecordLoader(Loop, None, None) ShmSizeLoader = _RecordLoader(ShmSize, None, None) union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_LoadListingRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_WorkReuseLoader_or_NetworkAccessLoader_or_InplaceUpdateRequirementLoader_or_ToolTimeLimitLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader_or_SecretsLoader_or_MPIRequirementLoader_or_CUDARequirementLoader_or_LoopLoader_or_ShmSizeLoader = _UnionLoader( ( InlineJavascriptRequirementLoader, SchemaDefRequirementLoader, LoadListingRequirementLoader, DockerRequirementLoader, SoftwareRequirementLoader, InitialWorkDirRequirementLoader, EnvVarRequirementLoader, ShellCommandRequirementLoader, ResourceRequirementLoader, WorkReuseLoader, NetworkAccessLoader, InplaceUpdateRequirementLoader, ToolTimeLimitLoader, SubworkflowFeatureRequirementLoader, ScatterFeatureRequirementLoader, MultipleInputFeatureRequirementLoader, StepInputExpressionRequirementLoader, SecretsLoader, MPIRequirementLoader, CUDARequirementLoader, LoopLoader, ShmSizeLoader, ) ) array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_LoadListingRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_WorkReuseLoader_or_NetworkAccessLoader_or_InplaceUpdateRequirementLoader_or_ToolTimeLimitLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader_or_SecretsLoader_or_MPIRequirementLoader_or_CUDARequirementLoader_or_LoopLoader_or_ShmSizeLoader = _ArrayLoader( union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_LoadListingRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_WorkReuseLoader_or_NetworkAccessLoader_or_InplaceUpdateRequirementLoader_or_ToolTimeLimitLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader_or_SecretsLoader_or_MPIRequirementLoader_or_CUDARequirementLoader_or_LoopLoader_or_ShmSizeLoader ) union_of_None_type_or_array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_LoadListingRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_WorkReuseLoader_or_NetworkAccessLoader_or_InplaceUpdateRequirementLoader_or_ToolTimeLimitLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader_or_SecretsLoader_or_MPIRequirementLoader_or_CUDARequirementLoader_or_LoopLoader_or_ShmSizeLoader_or_CWLObjectTypeLoader = _UnionLoader( ( None_type, array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_LoadListingRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_WorkReuseLoader_or_NetworkAccessLoader_or_InplaceUpdateRequirementLoader_or_ToolTimeLimitLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader_or_SecretsLoader_or_MPIRequirementLoader_or_CUDARequirementLoader_or_LoopLoader_or_ShmSizeLoader, CWLObjectTypeLoader, ) ) map_of_union_of_None_type_or_array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_LoadListingRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_WorkReuseLoader_or_NetworkAccessLoader_or_InplaceUpdateRequirementLoader_or_ToolTimeLimitLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader_or_SecretsLoader_or_MPIRequirementLoader_or_CUDARequirementLoader_or_LoopLoader_or_ShmSizeLoader_or_CWLObjectTypeLoader = _MapLoader( union_of_None_type_or_array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_LoadListingRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_WorkReuseLoader_or_NetworkAccessLoader_or_InplaceUpdateRequirementLoader_or_ToolTimeLimitLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader_or_SecretsLoader_or_MPIRequirementLoader_or_CUDARequirementLoader_or_LoopLoader_or_ShmSizeLoader_or_CWLObjectTypeLoader, "CWLInputFile", "@list", True, ) CWLInputFileLoader = map_of_union_of_None_type_or_array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_LoadListingRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_WorkReuseLoader_or_NetworkAccessLoader_or_InplaceUpdateRequirementLoader_or_ToolTimeLimitLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader_or_SecretsLoader_or_MPIRequirementLoader_or_CUDARequirementLoader_or_LoopLoader_or_ShmSizeLoader_or_CWLObjectTypeLoader CWLVersionLoader = _EnumLoader( ( "draft-2", "draft-3.dev1", "draft-3.dev2", "draft-3.dev3", "draft-3.dev4", "draft-3.dev5", "draft-3", "draft-4.dev1", "draft-4.dev2", "draft-4.dev3", "v1.0.dev4", "v1.0", "v1.1.0-dev1", "v1.1", "v1.2.0-dev1", "v1.2.0-dev2", "v1.2.0-dev3", "v1.2.0-dev4", "v1.2.0-dev5", "v1.2", ), "CWLVersion", ) """ Version symbols for published CWL document versions. """ LoadListingEnumLoader = _EnumLoader( ( "no_listing", "shallow_listing", "deep_listing", ), "LoadListingEnum", ) """ Specify the desired behavior for loading the `listing` field of a Directory object for use by expressions. no_listing: Do not load the directory listing. shallow_listing: Only load the top level listing, do not recurse into subdirectories. deep_listing: Load the directory listing and recursively load all subdirectories as well. """ ExpressionLoader = _ExpressionLoader(str) InputBindingLoader = _RecordLoader(InputBinding, None, None) InputRecordFieldLoader = _RecordLoader(InputRecordField, None, None) InputRecordSchemaLoader = _RecordLoader(InputRecordSchema, None, None) InputEnumSchemaLoader = _RecordLoader(InputEnumSchema, None, None) InputArraySchemaLoader = _RecordLoader(InputArraySchema, None, None) OutputRecordFieldLoader = _RecordLoader(OutputRecordField, None, None) OutputRecordSchemaLoader = _RecordLoader(OutputRecordSchema, None, None) OutputEnumSchemaLoader = _RecordLoader(OutputEnumSchema, None, None) OutputArraySchemaLoader = _RecordLoader(OutputArraySchema, None, None) SecondaryFileSchemaLoader = _RecordLoader(SecondaryFileSchema, None, None) EnvironmentDefLoader = _RecordLoader(EnvironmentDef, None, None) CommandLineBindingLoader = _RecordLoader(CommandLineBinding, None, None) CommandOutputBindingLoader = _RecordLoader(CommandOutputBinding, None, None) CommandInputRecordFieldLoader = _RecordLoader(CommandInputRecordField, None, None) CommandInputRecordSchemaLoader = _RecordLoader(CommandInputRecordSchema, None, None) CommandInputEnumSchemaLoader = _RecordLoader(CommandInputEnumSchema, None, None) CommandInputArraySchemaLoader = _RecordLoader(CommandInputArraySchema, None, None) CommandOutputRecordFieldLoader = _RecordLoader(CommandOutputRecordField, None, None) CommandOutputRecordSchemaLoader = _RecordLoader(CommandOutputRecordSchema, None, None) CommandOutputEnumSchemaLoader = _RecordLoader(CommandOutputEnumSchema, None, None) CommandOutputArraySchemaLoader = _RecordLoader(CommandOutputArraySchema, None, None) CommandInputParameterLoader = _RecordLoader(CommandInputParameter, None, None) CommandOutputParameterLoader = _RecordLoader(CommandOutputParameter, None, None) stdinLoader = _EnumLoader(("stdin",), "stdin") """ Only valid as a `type` for a `CommandLineTool` input with no `inputBinding` set. `stdin` must not be specified at the `CommandLineTool` level. The following ``` inputs: an_input_name: type: stdin ``` is equivalent to ``` inputs: an_input_name: type: File streamable: true stdin: $(inputs.an_input_name.path) ``` """ stdoutLoader = _EnumLoader(("stdout",), "stdout") """ Only valid as a `type` for a `CommandLineTool` output with no `outputBinding` set. The following ``` outputs: an_output_name: type: stdout stdout: a_stdout_file ``` is equivalent to ``` outputs: an_output_name: type: File streamable: true outputBinding: glob: a_stdout_file stdout: a_stdout_file ``` If there is no `stdout` name provided, a random filename will be created. For example, the following ``` outputs: an_output_name: type: stdout ``` is equivalent to ``` outputs: an_output_name: type: File streamable: true outputBinding: glob: random_stdout_filenameABCDEFG stdout: random_stdout_filenameABCDEFG ``` If the `CommandLineTool` contains logically chained commands (e.g. `echo a && echo b`) `stdout` must include the output of every command. """ stderrLoader = _EnumLoader(("stderr",), "stderr") """ Only valid as a `type` for a `CommandLineTool` output with no `outputBinding` set. The following ``` outputs: an_output_name: type: stderr stderr: a_stderr_file ``` is equivalent to ``` outputs: an_output_name: type: File streamable: true outputBinding: glob: a_stderr_file stderr: a_stderr_file ``` If there is no `stderr` name provided, a random filename will be created. For example, the following ``` outputs: an_output_name: type: stderr ``` is equivalent to ``` outputs: an_output_name: type: File streamable: true outputBinding: glob: random_stderr_filenameABCDEFG stderr: random_stderr_filenameABCDEFG ``` """ CommandLineToolLoader = _RecordLoader(CommandLineTool, None, None) SoftwarePackageLoader = _RecordLoader(SoftwarePackage, None, None) DirentLoader = _RecordLoader(Dirent, None, None) ExpressionToolOutputParameterLoader = _RecordLoader( ExpressionToolOutputParameter, None, None ) WorkflowInputParameterLoader = _RecordLoader(WorkflowInputParameter, None, None) ExpressionToolLoader = _RecordLoader(ExpressionTool, None, None) LinkMergeMethodLoader = _EnumLoader( ( "merge_nested", "merge_flattened", ), "LinkMergeMethod", ) """ The input link merge method, described in [WorkflowStepInput](#WorkflowStepInput). """ PickValueMethodLoader = _EnumLoader( ( "first_non_null", "the_only_non_null", "all_non_null", ), "PickValueMethod", ) """ Picking non-null values among inbound data links, described in [WorkflowStepInput](#WorkflowStepInput). """ WorkflowOutputParameterLoader = _RecordLoader(WorkflowOutputParameter, None, None) WorkflowStepInputLoader = _RecordLoader(WorkflowStepInput, None, None) WorkflowStepOutputLoader = _RecordLoader(WorkflowStepOutput, None, None) ScatterMethodLoader = _EnumLoader( ( "dotproduct", "nested_crossproduct", "flat_crossproduct", ), "ScatterMethod", ) """ The scatter method, as described in [workflow step scatter](#WorkflowStep). """ WorkflowStepLoader = _RecordLoader(WorkflowStep, None, None) WorkflowLoader = _RecordLoader(Workflow, None, None) OperationInputParameterLoader = _RecordLoader(OperationInputParameter, None, None) OperationOutputParameterLoader = _RecordLoader(OperationOutputParameter, None, None) OperationLoader = _RecordLoader(Operation, None, None) ProcessGeneratorLoader = _RecordLoader(ProcessGenerator, None, None) LoopInputLoader = _RecordLoader(LoopInput, None, None) array_of_strtype = _ArrayLoader(strtype) union_of_None_type_or_strtype_or_array_of_strtype = _UnionLoader( ( None_type, strtype, array_of_strtype, ) ) uri_strtype_True_False_None_None = _URILoader(strtype, True, False, None, None) union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype = _UnionLoader( ( PrimitiveTypeLoader, RecordSchemaLoader, EnumSchemaLoader, ArraySchemaLoader, MapSchemaLoader, UnionSchemaLoader, strtype, ) ) array_of_union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype = _ArrayLoader( union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype ) union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype_or_array_of_union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype = _UnionLoader( ( PrimitiveTypeLoader, RecordSchemaLoader, EnumSchemaLoader, ArraySchemaLoader, MapSchemaLoader, UnionSchemaLoader, strtype, array_of_union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype, ) ) typedsl_union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype_or_array_of_union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype_2 = _TypeDSLLoader( union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype_or_array_of_union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype, 2, "v1.1", ) array_of_RecordFieldLoader = _ArrayLoader(RecordFieldLoader) union_of_None_type_or_array_of_RecordFieldLoader = _UnionLoader( ( None_type, array_of_RecordFieldLoader, ) ) idmap_fields_union_of_None_type_or_array_of_RecordFieldLoader = _IdMapLoader( union_of_None_type_or_array_of_RecordFieldLoader, "name", "type" ) Record_nameLoader = _EnumLoader(("record",), "Record_name") typedsl_Record_nameLoader_2 = _TypeDSLLoader(Record_nameLoader, 2, "v1.1") union_of_None_type_or_strtype = _UnionLoader( ( None_type, strtype, ) ) uri_union_of_None_type_or_strtype_True_False_None_None = _URILoader( union_of_None_type_or_strtype, True, False, None, None ) uri_array_of_strtype_True_False_None_None = _URILoader( array_of_strtype, True, False, None, None ) Enum_nameLoader = _EnumLoader(("enum",), "Enum_name") typedsl_Enum_nameLoader_2 = _TypeDSLLoader(Enum_nameLoader, 2, "v1.1") uri_union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype_or_array_of_union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype_False_True_2_None = _URILoader( union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype_or_array_of_union_of_PrimitiveTypeLoader_or_RecordSchemaLoader_or_EnumSchemaLoader_or_ArraySchemaLoader_or_MapSchemaLoader_or_UnionSchemaLoader_or_strtype, False, True, 2, None, ) Array_nameLoader = _EnumLoader(("array",), "Array_name") typedsl_Array_nameLoader_2 = _TypeDSLLoader(Array_nameLoader, 2, "v1.1") Map_nameLoader = _EnumLoader(("map",), "Map_name") typedsl_Map_nameLoader_2 = _TypeDSLLoader(Map_nameLoader, 2, "v1.1") Union_nameLoader = _EnumLoader(("union",), "Union_name") typedsl_Union_nameLoader_2 = _TypeDSLLoader(Union_nameLoader, 2, "v1.1") union_of_PrimitiveTypeLoader_or_CWLRecordSchemaLoader_or_EnumSchemaLoader_or_CWLArraySchemaLoader_or_strtype = _UnionLoader( ( PrimitiveTypeLoader, CWLRecordSchemaLoader, EnumSchemaLoader, CWLArraySchemaLoader, strtype, ) ) array_of_union_of_PrimitiveTypeLoader_or_CWLRecordSchemaLoader_or_EnumSchemaLoader_or_CWLArraySchemaLoader_or_strtype = _ArrayLoader( union_of_PrimitiveTypeLoader_or_CWLRecordSchemaLoader_or_EnumSchemaLoader_or_CWLArraySchemaLoader_or_strtype ) union_of_PrimitiveTypeLoader_or_CWLRecordSchemaLoader_or_EnumSchemaLoader_or_CWLArraySchemaLoader_or_strtype_or_array_of_union_of_PrimitiveTypeLoader_or_CWLRecordSchemaLoader_or_EnumSchemaLoader_or_CWLArraySchemaLoader_or_strtype = _UnionLoader( ( PrimitiveTypeLoader, CWLRecordSchemaLoader, EnumSchemaLoader, CWLArraySchemaLoader, strtype, array_of_union_of_PrimitiveTypeLoader_or_CWLRecordSchemaLoader_or_EnumSchemaLoader_or_CWLArraySchemaLoader_or_strtype, ) ) uri_union_of_PrimitiveTypeLoader_or_CWLRecordSchemaLoader_or_EnumSchemaLoader_or_CWLArraySchemaLoader_or_strtype_or_array_of_union_of_PrimitiveTypeLoader_or_CWLRecordSchemaLoader_or_EnumSchemaLoader_or_CWLArraySchemaLoader_or_strtype_False_True_2_None = _URILoader( union_of_PrimitiveTypeLoader_or_CWLRecordSchemaLoader_or_EnumSchemaLoader_or_CWLArraySchemaLoader_or_strtype_or_array_of_union_of_PrimitiveTypeLoader_or_CWLRecordSchemaLoader_or_EnumSchemaLoader_or_CWLArraySchemaLoader_or_strtype, False, True, 2, None, ) typedsl_union_of_PrimitiveTypeLoader_or_CWLRecordSchemaLoader_or_EnumSchemaLoader_or_CWLArraySchemaLoader_or_strtype_or_array_of_union_of_PrimitiveTypeLoader_or_CWLRecordSchemaLoader_or_EnumSchemaLoader_or_CWLArraySchemaLoader_or_strtype_2 = _TypeDSLLoader( union_of_PrimitiveTypeLoader_or_CWLRecordSchemaLoader_or_EnumSchemaLoader_or_CWLArraySchemaLoader_or_strtype_or_array_of_union_of_PrimitiveTypeLoader_or_CWLRecordSchemaLoader_or_EnumSchemaLoader_or_CWLArraySchemaLoader_or_strtype, 2, "v1.1", ) array_of_CWLRecordFieldLoader = _ArrayLoader(CWLRecordFieldLoader) union_of_None_type_or_array_of_CWLRecordFieldLoader = _UnionLoader( ( None_type, array_of_CWLRecordFieldLoader, ) ) idmap_fields_union_of_None_type_or_array_of_CWLRecordFieldLoader = _IdMapLoader( union_of_None_type_or_array_of_CWLRecordFieldLoader, "name", "type" ) File_classLoader = _EnumLoader(("File",), "File_class") uri_File_classLoader_False_True_None_None = _URILoader( File_classLoader, False, True, None, None ) uri_union_of_None_type_or_strtype_False_False_None_None = _URILoader( union_of_None_type_or_strtype, False, False, None, None ) union_of_None_type_or_inttype = _UnionLoader( ( None_type, inttype, ) ) union_of_FileLoader_or_DirectoryLoader = _UnionLoader( ( FileLoader, DirectoryLoader, ) ) array_of_union_of_FileLoader_or_DirectoryLoader = _ArrayLoader( union_of_FileLoader_or_DirectoryLoader ) union_of_None_type_or_array_of_union_of_FileLoader_or_DirectoryLoader = _UnionLoader( ( None_type, array_of_union_of_FileLoader_or_DirectoryLoader, ) ) secondaryfilesdsl_union_of_None_type_or_array_of_union_of_FileLoader_or_DirectoryLoader = _UnionLoader( ( _SecondaryDSLLoader( union_of_None_type_or_array_of_union_of_FileLoader_or_DirectoryLoader ), union_of_None_type_or_array_of_union_of_FileLoader_or_DirectoryLoader, ) ) uri_union_of_None_type_or_strtype_True_False_None_True = _URILoader( union_of_None_type_or_strtype, True, False, None, True ) Directory_classLoader = _EnumLoader(("Directory",), "Directory_class") uri_Directory_classLoader_False_True_None_None = _URILoader( Directory_classLoader, False, True, None, None ) union_of_None_type_or_booltype = _UnionLoader( ( None_type, booltype, ) ) union_of_None_type_or_LoadListingEnumLoader = _UnionLoader( ( None_type, LoadListingEnumLoader, ) ) array_of_SecondaryFileSchemaLoader = _ArrayLoader(SecondaryFileSchemaLoader) union_of_None_type_or_SecondaryFileSchemaLoader_or_array_of_SecondaryFileSchemaLoader = _UnionLoader( ( None_type, SecondaryFileSchemaLoader, array_of_SecondaryFileSchemaLoader, ) ) secondaryfilesdsl_union_of_None_type_or_SecondaryFileSchemaLoader_or_array_of_SecondaryFileSchemaLoader = _UnionLoader( ( _SecondaryDSLLoader( union_of_None_type_or_SecondaryFileSchemaLoader_or_array_of_SecondaryFileSchemaLoader ), union_of_None_type_or_SecondaryFileSchemaLoader_or_array_of_SecondaryFileSchemaLoader, ) ) union_of_None_type_or_strtype_or_array_of_strtype_or_ExpressionLoader = _UnionLoader( ( None_type, strtype, array_of_strtype, ExpressionLoader, ) ) uri_union_of_None_type_or_strtype_or_array_of_strtype_or_ExpressionLoader_True_False_None_True = _URILoader( union_of_None_type_or_strtype_or_array_of_strtype_or_ExpressionLoader, True, False, None, True, ) union_of_None_type_or_strtype_or_ExpressionLoader = _UnionLoader( ( None_type, strtype, ExpressionLoader, ) ) uri_union_of_None_type_or_strtype_or_ExpressionLoader_True_False_None_True = _URILoader( union_of_None_type_or_strtype_or_ExpressionLoader, True, False, None, True ) union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype = _UnionLoader( ( CWLTypeLoader, InputRecordSchemaLoader, InputEnumSchemaLoader, InputArraySchemaLoader, strtype, ) ) array_of_union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype = _ArrayLoader( union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype ) union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype = _UnionLoader( ( CWLTypeLoader, InputRecordSchemaLoader, InputEnumSchemaLoader, InputArraySchemaLoader, strtype, array_of_union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype, ) ) typedsl_union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype_2 = _TypeDSLLoader( union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype, 2, "v1.1", ) array_of_InputRecordFieldLoader = _ArrayLoader(InputRecordFieldLoader) union_of_None_type_or_array_of_InputRecordFieldLoader = _UnionLoader( ( None_type, array_of_InputRecordFieldLoader, ) ) idmap_fields_union_of_None_type_or_array_of_InputRecordFieldLoader = _IdMapLoader( union_of_None_type_or_array_of_InputRecordFieldLoader, "name", "type" ) uri_union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype_False_True_2_None = _URILoader( union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_InputRecordSchemaLoader_or_InputEnumSchemaLoader_or_InputArraySchemaLoader_or_strtype, False, True, 2, None, ) union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype = _UnionLoader( ( CWLTypeLoader, OutputRecordSchemaLoader, OutputEnumSchemaLoader, OutputArraySchemaLoader, strtype, ) ) array_of_union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype = _ArrayLoader( union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype ) union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype = _UnionLoader( ( CWLTypeLoader, OutputRecordSchemaLoader, OutputEnumSchemaLoader, OutputArraySchemaLoader, strtype, array_of_union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype, ) ) typedsl_union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype_2 = _TypeDSLLoader( union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype, 2, "v1.1", ) array_of_OutputRecordFieldLoader = _ArrayLoader(OutputRecordFieldLoader) union_of_None_type_or_array_of_OutputRecordFieldLoader = _UnionLoader( ( None_type, array_of_OutputRecordFieldLoader, ) ) idmap_fields_union_of_None_type_or_array_of_OutputRecordFieldLoader = _IdMapLoader( union_of_None_type_or_array_of_OutputRecordFieldLoader, "name", "type" ) uri_union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype_False_True_2_None = _URILoader( union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_OutputRecordSchemaLoader_or_OutputEnumSchemaLoader_or_OutputArraySchemaLoader_or_strtype, False, True, 2, None, ) union_of_CommandInputParameterLoader_or_WorkflowInputParameterLoader_or_OperationInputParameterLoader = _UnionLoader( ( CommandInputParameterLoader, WorkflowInputParameterLoader, OperationInputParameterLoader, ) ) array_of_union_of_CommandInputParameterLoader_or_WorkflowInputParameterLoader_or_OperationInputParameterLoader = _ArrayLoader( union_of_CommandInputParameterLoader_or_WorkflowInputParameterLoader_or_OperationInputParameterLoader ) idmap_inputs_array_of_union_of_CommandInputParameterLoader_or_WorkflowInputParameterLoader_or_OperationInputParameterLoader = _IdMapLoader( array_of_union_of_CommandInputParameterLoader_or_WorkflowInputParameterLoader_or_OperationInputParameterLoader, "id", "type", ) union_of_CommandOutputParameterLoader_or_ExpressionToolOutputParameterLoader_or_WorkflowOutputParameterLoader_or_OperationOutputParameterLoader = _UnionLoader( ( CommandOutputParameterLoader, ExpressionToolOutputParameterLoader, WorkflowOutputParameterLoader, OperationOutputParameterLoader, ) ) array_of_union_of_CommandOutputParameterLoader_or_ExpressionToolOutputParameterLoader_or_WorkflowOutputParameterLoader_or_OperationOutputParameterLoader = _ArrayLoader( union_of_CommandOutputParameterLoader_or_ExpressionToolOutputParameterLoader_or_WorkflowOutputParameterLoader_or_OperationOutputParameterLoader ) idmap_outputs_array_of_union_of_CommandOutputParameterLoader_or_ExpressionToolOutputParameterLoader_or_WorkflowOutputParameterLoader_or_OperationOutputParameterLoader = _IdMapLoader( array_of_union_of_CommandOutputParameterLoader_or_ExpressionToolOutputParameterLoader_or_WorkflowOutputParameterLoader_or_OperationOutputParameterLoader, "id", "type", ) union_of_None_type_or_array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_LoadListingRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_WorkReuseLoader_or_NetworkAccessLoader_or_InplaceUpdateRequirementLoader_or_ToolTimeLimitLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader_or_SecretsLoader_or_MPIRequirementLoader_or_CUDARequirementLoader_or_LoopLoader_or_ShmSizeLoader = _UnionLoader( ( None_type, array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_LoadListingRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_WorkReuseLoader_or_NetworkAccessLoader_or_InplaceUpdateRequirementLoader_or_ToolTimeLimitLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader_or_SecretsLoader_or_MPIRequirementLoader_or_CUDARequirementLoader_or_LoopLoader_or_ShmSizeLoader, ) ) idmap_requirements_union_of_None_type_or_array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_LoadListingRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_WorkReuseLoader_or_NetworkAccessLoader_or_InplaceUpdateRequirementLoader_or_ToolTimeLimitLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader_or_SecretsLoader_or_MPIRequirementLoader_or_CUDARequirementLoader_or_LoopLoader_or_ShmSizeLoader = _IdMapLoader( union_of_None_type_or_array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_LoadListingRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_WorkReuseLoader_or_NetworkAccessLoader_or_InplaceUpdateRequirementLoader_or_ToolTimeLimitLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader_or_SecretsLoader_or_MPIRequirementLoader_or_CUDARequirementLoader_or_LoopLoader_or_ShmSizeLoader, "class", "None", ) union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_LoadListingRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_WorkReuseLoader_or_NetworkAccessLoader_or_InplaceUpdateRequirementLoader_or_ToolTimeLimitLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader_or_SecretsLoader_or_MPIRequirementLoader_or_CUDARequirementLoader_or_LoopLoader_or_ShmSizeLoader_or_Any_type = _UnionLoader( ( InlineJavascriptRequirementLoader, SchemaDefRequirementLoader, LoadListingRequirementLoader, DockerRequirementLoader, SoftwareRequirementLoader, InitialWorkDirRequirementLoader, EnvVarRequirementLoader, ShellCommandRequirementLoader, ResourceRequirementLoader, WorkReuseLoader, NetworkAccessLoader, InplaceUpdateRequirementLoader, ToolTimeLimitLoader, SubworkflowFeatureRequirementLoader, ScatterFeatureRequirementLoader, MultipleInputFeatureRequirementLoader, StepInputExpressionRequirementLoader, SecretsLoader, MPIRequirementLoader, CUDARequirementLoader, LoopLoader, ShmSizeLoader, Any_type, ) ) array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_LoadListingRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_WorkReuseLoader_or_NetworkAccessLoader_or_InplaceUpdateRequirementLoader_or_ToolTimeLimitLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader_or_SecretsLoader_or_MPIRequirementLoader_or_CUDARequirementLoader_or_LoopLoader_or_ShmSizeLoader_or_Any_type = _ArrayLoader( union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_LoadListingRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_WorkReuseLoader_or_NetworkAccessLoader_or_InplaceUpdateRequirementLoader_or_ToolTimeLimitLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader_or_SecretsLoader_or_MPIRequirementLoader_or_CUDARequirementLoader_or_LoopLoader_or_ShmSizeLoader_or_Any_type ) union_of_None_type_or_array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_LoadListingRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_WorkReuseLoader_or_NetworkAccessLoader_or_InplaceUpdateRequirementLoader_or_ToolTimeLimitLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader_or_SecretsLoader_or_MPIRequirementLoader_or_CUDARequirementLoader_or_LoopLoader_or_ShmSizeLoader_or_Any_type = _UnionLoader( ( None_type, array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_LoadListingRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_WorkReuseLoader_or_NetworkAccessLoader_or_InplaceUpdateRequirementLoader_or_ToolTimeLimitLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader_or_SecretsLoader_or_MPIRequirementLoader_or_CUDARequirementLoader_or_LoopLoader_or_ShmSizeLoader_or_Any_type, ) ) idmap_hints_union_of_None_type_or_array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_LoadListingRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_WorkReuseLoader_or_NetworkAccessLoader_or_InplaceUpdateRequirementLoader_or_ToolTimeLimitLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader_or_SecretsLoader_or_MPIRequirementLoader_or_CUDARequirementLoader_or_LoopLoader_or_ShmSizeLoader_or_Any_type = _IdMapLoader( union_of_None_type_or_array_of_union_of_InlineJavascriptRequirementLoader_or_SchemaDefRequirementLoader_or_LoadListingRequirementLoader_or_DockerRequirementLoader_or_SoftwareRequirementLoader_or_InitialWorkDirRequirementLoader_or_EnvVarRequirementLoader_or_ShellCommandRequirementLoader_or_ResourceRequirementLoader_or_WorkReuseLoader_or_NetworkAccessLoader_or_InplaceUpdateRequirementLoader_or_ToolTimeLimitLoader_or_SubworkflowFeatureRequirementLoader_or_ScatterFeatureRequirementLoader_or_MultipleInputFeatureRequirementLoader_or_StepInputExpressionRequirementLoader_or_SecretsLoader_or_MPIRequirementLoader_or_CUDARequirementLoader_or_LoopLoader_or_ShmSizeLoader_or_Any_type, "class", "None", ) union_of_None_type_or_CWLVersionLoader = _UnionLoader( ( None_type, CWLVersionLoader, ) ) uri_union_of_None_type_or_CWLVersionLoader_False_True_None_None = _URILoader( union_of_None_type_or_CWLVersionLoader, False, True, None, None ) union_of_None_type_or_array_of_strtype = _UnionLoader( ( None_type, array_of_strtype, ) ) uri_union_of_None_type_or_array_of_strtype_True_False_None_None = _URILoader( union_of_None_type_or_array_of_strtype, True, False, None, None ) InlineJavascriptRequirement_classLoader = _EnumLoader( ("InlineJavascriptRequirement",), "InlineJavascriptRequirement_class" ) uri_InlineJavascriptRequirement_classLoader_False_True_None_None = _URILoader( InlineJavascriptRequirement_classLoader, False, True, None, None ) SchemaDefRequirement_classLoader = _EnumLoader( ("SchemaDefRequirement",), "SchemaDefRequirement_class" ) uri_SchemaDefRequirement_classLoader_False_True_None_None = _URILoader( SchemaDefRequirement_classLoader, False, True, None, None ) union_of_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader = _UnionLoader( ( CommandInputRecordSchemaLoader, CommandInputEnumSchemaLoader, CommandInputArraySchemaLoader, ) ) array_of_union_of_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader = _ArrayLoader( union_of_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader ) union_of_strtype_or_ExpressionLoader = _UnionLoader( ( strtype, ExpressionLoader, ) ) union_of_None_type_or_booltype_or_ExpressionLoader = _UnionLoader( ( None_type, booltype, ExpressionLoader, ) ) LoadListingRequirement_classLoader = _EnumLoader( ("LoadListingRequirement",), "LoadListingRequirement_class" ) uri_LoadListingRequirement_classLoader_False_True_None_None = _URILoader( LoadListingRequirement_classLoader, False, True, None, None ) union_of_None_type_or_inttype_or_ExpressionLoader = _UnionLoader( ( None_type, inttype, ExpressionLoader, ) ) union_of_None_type_or_strtype_or_ExpressionLoader_or_array_of_strtype = _UnionLoader( ( None_type, strtype, ExpressionLoader, array_of_strtype, ) ) union_of_None_type_or_ExpressionLoader = _UnionLoader( ( None_type, ExpressionLoader, ) ) union_of_None_type_or_CommandLineBindingLoader = _UnionLoader( ( None_type, CommandLineBindingLoader, ) ) union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype = _UnionLoader( ( CWLTypeLoader, CommandInputRecordSchemaLoader, CommandInputEnumSchemaLoader, CommandInputArraySchemaLoader, strtype, ) ) array_of_union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype = _ArrayLoader( union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype ) union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype = _UnionLoader( ( CWLTypeLoader, CommandInputRecordSchemaLoader, CommandInputEnumSchemaLoader, CommandInputArraySchemaLoader, strtype, array_of_union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype, ) ) typedsl_union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype_2 = _TypeDSLLoader( union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype, 2, "v1.1", ) array_of_CommandInputRecordFieldLoader = _ArrayLoader(CommandInputRecordFieldLoader) union_of_None_type_or_array_of_CommandInputRecordFieldLoader = _UnionLoader( ( None_type, array_of_CommandInputRecordFieldLoader, ) ) idmap_fields_union_of_None_type_or_array_of_CommandInputRecordFieldLoader = ( _IdMapLoader( union_of_None_type_or_array_of_CommandInputRecordFieldLoader, "name", "type" ) ) uri_union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype_False_True_2_None = _URILoader( union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype, False, True, 2, None, ) union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype = _UnionLoader( ( CWLTypeLoader, CommandOutputRecordSchemaLoader, CommandOutputEnumSchemaLoader, CommandOutputArraySchemaLoader, strtype, ) ) array_of_union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype = _ArrayLoader( union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype ) union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype = _UnionLoader( ( CWLTypeLoader, CommandOutputRecordSchemaLoader, CommandOutputEnumSchemaLoader, CommandOutputArraySchemaLoader, strtype, array_of_union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype, ) ) typedsl_union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype_2 = _TypeDSLLoader( union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype, 2, "v1.1", ) union_of_None_type_or_CommandOutputBindingLoader = _UnionLoader( ( None_type, CommandOutputBindingLoader, ) ) array_of_CommandOutputRecordFieldLoader = _ArrayLoader(CommandOutputRecordFieldLoader) union_of_None_type_or_array_of_CommandOutputRecordFieldLoader = _UnionLoader( ( None_type, array_of_CommandOutputRecordFieldLoader, ) ) idmap_fields_union_of_None_type_or_array_of_CommandOutputRecordFieldLoader = ( _IdMapLoader( union_of_None_type_or_array_of_CommandOutputRecordFieldLoader, "name", "type" ) ) uri_union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype_False_True_2_None = _URILoader( union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype, False, True, 2, None, ) union_of_CWLTypeLoader_or_stdinLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype = _UnionLoader( ( CWLTypeLoader, stdinLoader, CommandInputRecordSchemaLoader, CommandInputEnumSchemaLoader, CommandInputArraySchemaLoader, strtype, array_of_union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype, ) ) typedsl_union_of_CWLTypeLoader_or_stdinLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype_2 = _TypeDSLLoader( union_of_CWLTypeLoader_or_stdinLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandInputRecordSchemaLoader_or_CommandInputEnumSchemaLoader_or_CommandInputArraySchemaLoader_or_strtype, 2, "v1.1", ) union_of_CWLTypeLoader_or_stdoutLoader_or_stderrLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype = _UnionLoader( ( CWLTypeLoader, stdoutLoader, stderrLoader, CommandOutputRecordSchemaLoader, CommandOutputEnumSchemaLoader, CommandOutputArraySchemaLoader, strtype, array_of_union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype, ) ) typedsl_union_of_CWLTypeLoader_or_stdoutLoader_or_stderrLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype_2 = _TypeDSLLoader( union_of_CWLTypeLoader_or_stdoutLoader_or_stderrLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype_or_array_of_union_of_CWLTypeLoader_or_CommandOutputRecordSchemaLoader_or_CommandOutputEnumSchemaLoader_or_CommandOutputArraySchemaLoader_or_strtype, 2, "v1.1", ) CommandLineTool_classLoader = _EnumLoader(("CommandLineTool",), "CommandLineTool_class") uri_CommandLineTool_classLoader_False_True_None_None = _URILoader( CommandLineTool_classLoader, False, True, None, None ) array_of_CommandInputParameterLoader = _ArrayLoader(CommandInputParameterLoader) idmap_inputs_array_of_CommandInputParameterLoader = _IdMapLoader( array_of_CommandInputParameterLoader, "id", "type" ) array_of_CommandOutputParameterLoader = _ArrayLoader(CommandOutputParameterLoader) idmap_outputs_array_of_CommandOutputParameterLoader = _IdMapLoader( array_of_CommandOutputParameterLoader, "id", "type" ) union_of_strtype_or_ExpressionLoader_or_CommandLineBindingLoader = _UnionLoader( ( strtype, ExpressionLoader, CommandLineBindingLoader, ) ) array_of_union_of_strtype_or_ExpressionLoader_or_CommandLineBindingLoader = ( _ArrayLoader(union_of_strtype_or_ExpressionLoader_or_CommandLineBindingLoader) ) union_of_None_type_or_array_of_union_of_strtype_or_ExpressionLoader_or_CommandLineBindingLoader = _UnionLoader( ( None_type, array_of_union_of_strtype_or_ExpressionLoader_or_CommandLineBindingLoader, ) ) array_of_inttype = _ArrayLoader(inttype) union_of_None_type_or_array_of_inttype = _UnionLoader( ( None_type, array_of_inttype, ) ) DockerRequirement_classLoader = _EnumLoader( ("DockerRequirement",), "DockerRequirement_class" ) uri_DockerRequirement_classLoader_False_True_None_None = _URILoader( DockerRequirement_classLoader, False, True, None, None ) SoftwareRequirement_classLoader = _EnumLoader( ("SoftwareRequirement",), "SoftwareRequirement_class" ) uri_SoftwareRequirement_classLoader_False_True_None_None = _URILoader( SoftwareRequirement_classLoader, False, True, None, None ) array_of_SoftwarePackageLoader = _ArrayLoader(SoftwarePackageLoader) idmap_packages_array_of_SoftwarePackageLoader = _IdMapLoader( array_of_SoftwarePackageLoader, "package", "specs" ) uri_union_of_None_type_or_array_of_strtype_False_False_None_True = _URILoader( union_of_None_type_or_array_of_strtype, False, False, None, True ) InitialWorkDirRequirement_classLoader = _EnumLoader( ("InitialWorkDirRequirement",), "InitialWorkDirRequirement_class" ) uri_InitialWorkDirRequirement_classLoader_False_True_None_None = _URILoader( InitialWorkDirRequirement_classLoader, False, True, None, None ) union_of_None_type_or_DirentLoader_or_ExpressionLoader_or_FileLoader_or_DirectoryLoader_or_array_of_union_of_FileLoader_or_DirectoryLoader = _UnionLoader( ( None_type, DirentLoader, ExpressionLoader, FileLoader, DirectoryLoader, array_of_union_of_FileLoader_or_DirectoryLoader, ) ) array_of_union_of_None_type_or_DirentLoader_or_ExpressionLoader_or_FileLoader_or_DirectoryLoader_or_array_of_union_of_FileLoader_or_DirectoryLoader = _ArrayLoader( union_of_None_type_or_DirentLoader_or_ExpressionLoader_or_FileLoader_or_DirectoryLoader_or_array_of_union_of_FileLoader_or_DirectoryLoader ) union_of_ExpressionLoader_or_array_of_union_of_None_type_or_DirentLoader_or_ExpressionLoader_or_FileLoader_or_DirectoryLoader_or_array_of_union_of_FileLoader_or_DirectoryLoader = _UnionLoader( ( ExpressionLoader, array_of_union_of_None_type_or_DirentLoader_or_ExpressionLoader_or_FileLoader_or_DirectoryLoader_or_array_of_union_of_FileLoader_or_DirectoryLoader, ) ) EnvVarRequirement_classLoader = _EnumLoader( ("EnvVarRequirement",), "EnvVarRequirement_class" ) uri_EnvVarRequirement_classLoader_False_True_None_None = _URILoader( EnvVarRequirement_classLoader, False, True, None, None ) array_of_EnvironmentDefLoader = _ArrayLoader(EnvironmentDefLoader) idmap_envDef_array_of_EnvironmentDefLoader = _IdMapLoader( array_of_EnvironmentDefLoader, "envName", "envValue" ) ShellCommandRequirement_classLoader = _EnumLoader( ("ShellCommandRequirement",), "ShellCommandRequirement_class" ) uri_ShellCommandRequirement_classLoader_False_True_None_None = _URILoader( ShellCommandRequirement_classLoader, False, True, None, None ) ResourceRequirement_classLoader = _EnumLoader( ("ResourceRequirement",), "ResourceRequirement_class" ) uri_ResourceRequirement_classLoader_False_True_None_None = _URILoader( ResourceRequirement_classLoader, False, True, None, None ) union_of_None_type_or_inttype_or_floattype_or_ExpressionLoader = _UnionLoader( ( None_type, inttype, floattype, ExpressionLoader, ) ) WorkReuse_classLoader = _EnumLoader(("WorkReuse",), "WorkReuse_class") uri_WorkReuse_classLoader_False_True_None_None = _URILoader( WorkReuse_classLoader, False, True, None, None ) union_of_booltype_or_ExpressionLoader = _UnionLoader( ( booltype, ExpressionLoader, ) ) NetworkAccess_classLoader = _EnumLoader(("NetworkAccess",), "NetworkAccess_class") uri_NetworkAccess_classLoader_False_True_None_None = _URILoader( NetworkAccess_classLoader, False, True, None, None ) InplaceUpdateRequirement_classLoader = _EnumLoader( ("InplaceUpdateRequirement",), "InplaceUpdateRequirement_class" ) uri_InplaceUpdateRequirement_classLoader_False_True_None_None = _URILoader( InplaceUpdateRequirement_classLoader, False, True, None, None ) ToolTimeLimit_classLoader = _EnumLoader(("ToolTimeLimit",), "ToolTimeLimit_class") uri_ToolTimeLimit_classLoader_False_True_None_None = _URILoader( ToolTimeLimit_classLoader, False, True, None, None ) union_of_inttype_or_ExpressionLoader = _UnionLoader( ( inttype, ExpressionLoader, ) ) union_of_None_type_or_InputBindingLoader = _UnionLoader( ( None_type, InputBindingLoader, ) ) ExpressionTool_classLoader = _EnumLoader(("ExpressionTool",), "ExpressionTool_class") uri_ExpressionTool_classLoader_False_True_None_None = _URILoader( ExpressionTool_classLoader, False, True, None, None ) array_of_WorkflowInputParameterLoader = _ArrayLoader(WorkflowInputParameterLoader) idmap_inputs_array_of_WorkflowInputParameterLoader = _IdMapLoader( array_of_WorkflowInputParameterLoader, "id", "type" ) array_of_ExpressionToolOutputParameterLoader = _ArrayLoader( ExpressionToolOutputParameterLoader ) idmap_outputs_array_of_ExpressionToolOutputParameterLoader = _IdMapLoader( array_of_ExpressionToolOutputParameterLoader, "id", "type" ) uri_union_of_None_type_or_strtype_or_array_of_strtype_False_False_1_None = _URILoader( union_of_None_type_or_strtype_or_array_of_strtype, False, False, 1, None ) union_of_None_type_or_LinkMergeMethodLoader = _UnionLoader( ( None_type, LinkMergeMethodLoader, ) ) union_of_None_type_or_PickValueMethodLoader = _UnionLoader( ( None_type, PickValueMethodLoader, ) ) uri_union_of_None_type_or_strtype_or_array_of_strtype_False_False_2_None = _URILoader( union_of_None_type_or_strtype_or_array_of_strtype, False, False, 2, None ) array_of_WorkflowStepInputLoader = _ArrayLoader(WorkflowStepInputLoader) idmap_in__array_of_WorkflowStepInputLoader = _IdMapLoader( array_of_WorkflowStepInputLoader, "id", "source" ) union_of_strtype_or_WorkflowStepOutputLoader = _UnionLoader( ( strtype, WorkflowStepOutputLoader, ) ) array_of_union_of_strtype_or_WorkflowStepOutputLoader = _ArrayLoader( union_of_strtype_or_WorkflowStepOutputLoader ) union_of_array_of_union_of_strtype_or_WorkflowStepOutputLoader = _UnionLoader( (array_of_union_of_strtype_or_WorkflowStepOutputLoader,) ) uri_union_of_array_of_union_of_strtype_or_WorkflowStepOutputLoader_True_False_None_None = _URILoader( union_of_array_of_union_of_strtype_or_WorkflowStepOutputLoader, True, False, None, None, ) array_of_Any_type = _ArrayLoader(Any_type) union_of_None_type_or_array_of_Any_type = _UnionLoader( ( None_type, array_of_Any_type, ) ) idmap_hints_union_of_None_type_or_array_of_Any_type = _IdMapLoader( union_of_None_type_or_array_of_Any_type, "class", "None" ) union_of_strtype_or_CommandLineToolLoader_or_ExpressionToolLoader_or_WorkflowLoader_or_OperationLoader_or_ProcessGeneratorLoader = _UnionLoader( ( strtype, CommandLineToolLoader, ExpressionToolLoader, WorkflowLoader, OperationLoader, ProcessGeneratorLoader, ) ) uri_union_of_strtype_or_CommandLineToolLoader_or_ExpressionToolLoader_or_WorkflowLoader_or_OperationLoader_or_ProcessGeneratorLoader_False_False_None_None = _URILoader( union_of_strtype_or_CommandLineToolLoader_or_ExpressionToolLoader_or_WorkflowLoader_or_OperationLoader_or_ProcessGeneratorLoader, False, False, None, None, ) uri_union_of_None_type_or_strtype_or_array_of_strtype_False_False_0_None = _URILoader( union_of_None_type_or_strtype_or_array_of_strtype, False, False, 0, None ) union_of_None_type_or_ScatterMethodLoader = _UnionLoader( ( None_type, ScatterMethodLoader, ) ) uri_union_of_None_type_or_ScatterMethodLoader_False_True_None_None = _URILoader( union_of_None_type_or_ScatterMethodLoader, False, True, None, None ) Workflow_classLoader = _EnumLoader(("Workflow",), "Workflow_class") uri_Workflow_classLoader_False_True_None_None = _URILoader( Workflow_classLoader, False, True, None, None ) array_of_WorkflowOutputParameterLoader = _ArrayLoader(WorkflowOutputParameterLoader) idmap_outputs_array_of_WorkflowOutputParameterLoader = _IdMapLoader( array_of_WorkflowOutputParameterLoader, "id", "type" ) array_of_WorkflowStepLoader = _ArrayLoader(WorkflowStepLoader) union_of_array_of_WorkflowStepLoader = _UnionLoader((array_of_WorkflowStepLoader,)) idmap_steps_union_of_array_of_WorkflowStepLoader = _IdMapLoader( union_of_array_of_WorkflowStepLoader, "id", "None" ) SubworkflowFeatureRequirement_classLoader = _EnumLoader( ("SubworkflowFeatureRequirement",), "SubworkflowFeatureRequirement_class" ) uri_SubworkflowFeatureRequirement_classLoader_False_True_None_None = _URILoader( SubworkflowFeatureRequirement_classLoader, False, True, None, None ) ScatterFeatureRequirement_classLoader = _EnumLoader( ("ScatterFeatureRequirement",), "ScatterFeatureRequirement_class" ) uri_ScatterFeatureRequirement_classLoader_False_True_None_None = _URILoader( ScatterFeatureRequirement_classLoader, False, True, None, None ) MultipleInputFeatureRequirement_classLoader = _EnumLoader( ("MultipleInputFeatureRequirement",), "MultipleInputFeatureRequirement_class" ) uri_MultipleInputFeatureRequirement_classLoader_False_True_None_None = _URILoader( MultipleInputFeatureRequirement_classLoader, False, True, None, None ) StepInputExpressionRequirement_classLoader = _EnumLoader( ("StepInputExpressionRequirement",), "StepInputExpressionRequirement_class" ) uri_StepInputExpressionRequirement_classLoader_False_True_None_None = _URILoader( StepInputExpressionRequirement_classLoader, False, True, None, None ) Operation_classLoader = _EnumLoader(("Operation",), "Operation_class") uri_Operation_classLoader_False_True_None_None = _URILoader( Operation_classLoader, False, True, None, None ) array_of_OperationInputParameterLoader = _ArrayLoader(OperationInputParameterLoader) idmap_inputs_array_of_OperationInputParameterLoader = _IdMapLoader( array_of_OperationInputParameterLoader, "id", "type" ) array_of_OperationOutputParameterLoader = _ArrayLoader(OperationOutputParameterLoader) idmap_outputs_array_of_OperationOutputParameterLoader = _IdMapLoader( array_of_OperationOutputParameterLoader, "id", "type" ) uri_strtype_False_True_None_None = _URILoader(strtype, False, True, None, None) uri_array_of_strtype_False_False_0_None = _URILoader( array_of_strtype, False, False, 0, None ) union_of_strtype_or_array_of_strtype = _UnionLoader( ( strtype, array_of_strtype, ) ) union_of_None_type_or_Any_type = _UnionLoader( ( None_type, Any_type, ) ) array_of_LoopInputLoader = _ArrayLoader(LoopInputLoader) idmap_loop_array_of_LoopInputLoader = _IdMapLoader( array_of_LoopInputLoader, "id", "loopSource" ) LoopOutputModesLoader = _EnumLoader( ( "last", "all", ), "LoopOutputModes", ) union_of_CommandLineToolLoader_or_ExpressionToolLoader_or_WorkflowLoader_or_OperationLoader_or_ProcessGeneratorLoader = _UnionLoader( ( CommandLineToolLoader, ExpressionToolLoader, WorkflowLoader, OperationLoader, ProcessGeneratorLoader, ) ) array_of_union_of_CommandLineToolLoader_or_ExpressionToolLoader_or_WorkflowLoader_or_OperationLoader_or_ProcessGeneratorLoader = _ArrayLoader( union_of_CommandLineToolLoader_or_ExpressionToolLoader_or_WorkflowLoader_or_OperationLoader_or_ProcessGeneratorLoader ) union_of_CommandLineToolLoader_or_ExpressionToolLoader_or_WorkflowLoader_or_OperationLoader_or_ProcessGeneratorLoader_or_array_of_union_of_CommandLineToolLoader_or_ExpressionToolLoader_or_WorkflowLoader_or_OperationLoader_or_ProcessGeneratorLoader = _UnionLoader( ( CommandLineToolLoader, ExpressionToolLoader, WorkflowLoader, OperationLoader, ProcessGeneratorLoader, array_of_union_of_CommandLineToolLoader_or_ExpressionToolLoader_or_WorkflowLoader_or_OperationLoader_or_ProcessGeneratorLoader, ) ) CWLObjectTypeLoader.add_loaders( ( booltype, inttype, floattype, strtype, FileLoader, DirectoryLoader, array_of_union_of_None_type_or_CWLObjectTypeLoader, map_of_union_of_None_type_or_CWLObjectTypeLoader, ) ) def load_document( doc: Any, baseuri: Optional[str] = None, loadingOptions: Optional[LoadingOptions] = None, ) -> Any: if baseuri is None: baseuri = file_uri(os.getcwd()) + "/" if loadingOptions is None: loadingOptions = LoadingOptions() result, metadata = _document_load( union_of_CommandLineToolLoader_or_ExpressionToolLoader_or_WorkflowLoader_or_OperationLoader_or_ProcessGeneratorLoader_or_array_of_union_of_CommandLineToolLoader_or_ExpressionToolLoader_or_WorkflowLoader_or_OperationLoader_or_ProcessGeneratorLoader, doc, baseuri, loadingOptions, ) return result def load_document_with_metadata( doc: Any, baseuri: Optional[str] = None, loadingOptions: Optional[LoadingOptions] = None, addl_metadata_fields: Optional[MutableSequence[str]] = None, ) -> Any: if baseuri is None: baseuri = file_uri(os.getcwd()) + "/" if loadingOptions is None: loadingOptions = LoadingOptions(fileuri=baseuri) return _document_load( union_of_CommandLineToolLoader_or_ExpressionToolLoader_or_WorkflowLoader_or_OperationLoader_or_ProcessGeneratorLoader_or_array_of_union_of_CommandLineToolLoader_or_ExpressionToolLoader_or_WorkflowLoader_or_OperationLoader_or_ProcessGeneratorLoader, doc, baseuri, loadingOptions, addl_metadata_fields=addl_metadata_fields, ) def load_document_by_string( string: Any, uri: str, loadingOptions: Optional[LoadingOptions] = None, ) -> Any: yaml = yaml_no_ts() result = yaml.load(string) add_lc_filename(result, uri) if loadingOptions is None: loadingOptions = LoadingOptions(fileuri=uri) result, metadata = _document_load( union_of_CommandLineToolLoader_or_ExpressionToolLoader_or_WorkflowLoader_or_OperationLoader_or_ProcessGeneratorLoader_or_array_of_union_of_CommandLineToolLoader_or_ExpressionToolLoader_or_WorkflowLoader_or_OperationLoader_or_ProcessGeneratorLoader, result, uri, loadingOptions, ) return result def load_document_by_yaml( yaml: Any, uri: str, loadingOptions: Optional[LoadingOptions] = None, ) -> Any: """ Shortcut to load via a YAML object. yaml: must be from ruamel.yaml.main.YAML.load with preserve_quotes=True """ add_lc_filename(yaml, uri) if loadingOptions is None: loadingOptions = LoadingOptions(fileuri=uri) result, metadata = _document_load( union_of_CommandLineToolLoader_or_ExpressionToolLoader_or_WorkflowLoader_or_OperationLoader_or_ProcessGeneratorLoader_or_array_of_union_of_CommandLineToolLoader_or_ExpressionToolLoader_or_WorkflowLoader_or_OperationLoader_or_ProcessGeneratorLoader, yaml, uri, loadingOptions, ) return result cwl_utils-0.41/cwl_utils/parser/cwl_v1_2_utils.py0000644000000000000000000006447313615410400017110 0ustar00# SPDX-License-Identifier: Apache-2.0 import hashlib import logging from collections import namedtuple from collections.abc import MutableMapping, MutableSequence from io import StringIO from pathlib import Path from typing import IO, Any, cast from urllib.parse import urldefrag from schema_salad.exceptions import ValidationException from schema_salad.sourceline import SourceLine, add_lc_filename from schema_salad.utils import aslist, json_dumps, yaml_no_ts import cwl_utils.parser import cwl_utils.parser.cwl_v1_2 as cwl import cwl_utils.parser.utils from cwl_utils.errors import WorkflowException from cwl_utils.utils import yaml_dumps CONTENT_LIMIT: int = 64 * 1024 _logger = logging.getLogger("cwl_utils") SrcSink = namedtuple("SrcSink", ["src", "sink", "linkMerge", "message"]) def _compare_records( src: cwl.RecordSchema, sink: cwl.RecordSchema, strict: bool = False ) -> bool: """ Compare two records, ensuring they have compatible fields. This handles normalizing record names, which will be relative to workflow step, so that they can be compared. """ srcfields = {cwl.shortname(field.name): field.type_ for field in (src.fields or {})} sinkfields = { cwl.shortname(field.name): field.type_ for field in (sink.fields or {}) } for key in sinkfields.keys(): if ( not can_assign_src_to_sink( srcfields.get(key, "null"), sinkfields.get(key, "null"), strict ) and sinkfields.get(key) is not None ): _logger.info( "Record comparison failure for %s and %s\n" "Did not match fields for %s: %s and %s", cast(cwl.InputRecordSchema | cwl.CommandOutputRecordSchema, src).name, cast(cwl.InputRecordSchema | cwl.CommandOutputRecordSchema, sink).name, key, srcfields.get(key), sinkfields.get(key), ) return False return True def _compare_type(type1: Any, type2: Any) -> bool: match (type1, type1): case cwl.ArraySchema() as t1, cwl.ArraySchema() as t2: return _compare_type(t1.items, t2.items) case cwl.RecordSchema(), cwl.RecordSchema(): fields1 = { cwl.shortname(field.name): field.type_ for field in (type1.fields or {}) } fields2 = { cwl.shortname(field.name): field.type_ for field in (type2.fields or {}) } if fields1.keys() != fields2.keys(): return False return all(_compare_type(fields1[k], fields2[k]) for k in fields1.keys()) case MutableSequence(), MutableSequence(): if len(type1) != len(type2): return False for t3 in type1: if not any(_compare_type(t3, t2) for t2 in type2): return False return True return bool(type1 == type2) def _is_all_output_method_loop_step( param_to_step: dict[str, cwl.WorkflowStep], parm_id: str ) -> bool: if (source_step := param_to_step.get(parm_id)) is not None: for requirement in source_step.requirements or []: if isinstance(requirement, cwl.Loop) and requirement.outputMethod == "all": return True return False def _is_conditional_step( param_to_step: dict[str, cwl.WorkflowStep], parm_id: str ) -> bool: if (source_step := param_to_step.get(parm_id)) is not None: if source_step.when is not None: return True return False def _inputfile_load( doc: str | MutableMapping[str, Any] | MutableSequence[Any], baseuri: str, loadingOptions: cwl.LoadingOptions, addl_metadata_fields: MutableSequence[str] | None = None, ) -> tuple[Any, cwl.LoadingOptions]: loader = cwl.CWLInputFileLoader match doc: case str(): url = loadingOptions.fetcher.urljoin(baseuri, doc) if url in loadingOptions.idx: return loadingOptions.idx[url] doc_url, frg = urldefrag(url) text = loadingOptions.fetcher.fetch_text(doc_url) textIO = StringIO(text) textIO.name = doc_url yaml = yaml_no_ts() result = yaml.load(textIO) add_lc_filename(result, doc_url) loadingOptions = cwl.LoadingOptions( copyfrom=loadingOptions, fileuri=doc_url ) _inputfile_load( result, doc_url, loadingOptions, ) return loadingOptions.idx[url] case MutableMapping(): addl_metadata = {} if addl_metadata_fields is not None: for mf in addl_metadata_fields: if mf in doc: addl_metadata[mf] = doc[mf] loadingOptions = cwl.LoadingOptions( copyfrom=loadingOptions, baseuri=baseuri, addl_metadata=addl_metadata, ) loadingOptions.idx[baseuri] = ( loader.load(doc, baseuri, loadingOptions, docRoot=baseuri), loadingOptions, ) return loadingOptions.idx[baseuri] case MutableSequence(): loadingOptions.idx[baseuri] = ( loader.load(doc, baseuri, loadingOptions), loadingOptions, ) return loadingOptions.idx[baseuri] case _: raise ValidationException( "Expected URI string, MutableMapping or MutableSequence, got %s" % type(doc) ) def can_assign_src_to_sink(src: Any, sink: Any, strict: bool = False) -> bool: """ Check for identical type specifications, ignoring extra keys like inputBinding. src: admissible source types sink: admissible sink types In non-strict comparison, at least one source type must match one sink type, except for 'null'. In strict comparison, all source types must match at least one sink type. """ if "Any" in (src, sink): return True if isinstance(src, cwl.ArraySchema) and isinstance(sink, cwl.ArraySchema): return can_assign_src_to_sink(src.items, sink.items, strict) if isinstance(src, cwl.RecordSchema) and isinstance(sink, cwl.RecordSchema): return _compare_records(src, sink, strict) if isinstance(src, MutableSequence): if strict: for this_src in src: if not can_assign_src_to_sink(this_src, sink): return False return True for this_src in src: if this_src != "null" and can_assign_src_to_sink(this_src, sink): return True return False if isinstance(sink, MutableSequence): for this_sink in sink: if can_assign_src_to_sink(src, this_sink): return True return False return bool(src == sink) def check_all_types( src_dict: dict[str, Any], sinks: MutableSequence[cwl.WorkflowStepInput | cwl.WorkflowOutputParameter], param_to_step: dict[str, cwl.WorkflowStep], type_dict: dict[str, Any], ) -> dict[str, list[SrcSink]]: """Given a list of sinks, check if their types match with the types of their sources.""" validation: dict[str, list[SrcSink]] = {"warning": [], "exception": []} for sink in sinks: extra_message = ( "pickValue is %s" % sink.pickValue if sink.pickValue is not None else None ) sink_type = type_dict[sink.id] match sink: case cwl.WorkflowOutputParameter(): sourceName = "outputSource" sourceField = sink.outputSource case cwl.WorkflowStepInput(): sourceName = "source" sourceField = sink.source case _: continue if sourceField is not None: if isinstance(sourceField, MutableSequence) and len(sourceField) > 1: linkMerge: str | None = sink.linkMerge or ( "merge_nested" if len(sourceField) > 1 else None ) if sink.pickValue in ("first_non_null", "the_only_non_null"): linkMerge = None srcs_of_sink = [] for parm_id in sourceField: srcs_of_sink += [src_dict[parm_id]] if ( _is_conditional_step(param_to_step, parm_id) and sink.pickValue is None ): src_typ = aslist(type_dict[src_dict[parm_id].id]) if "null" not in src_typ: src_typ = ["null"] + cast(list[Any], src_typ) if ( not isinstance(sink_type, MutableSequence) or "null" not in sink_type ): validation["warning"].append( SrcSink( src_dict[parm_id], sink, linkMerge, message="Source is from conditional step, but pickValue is not used", ) ) type_dict[src_dict[parm_id].id] = src_typ if _is_all_output_method_loop_step(param_to_step, parm_id): src_typ = type_dict[src_dict[parm_id].id] type_dict[src_dict[parm_id].id] = cwl.ArraySchema( items=src_typ, type_="array" ) else: if isinstance(sourceField, MutableSequence): parm_id = cast(str, sourceField[0]) else: parm_id = cast(str, sourceField) if parm_id not in src_dict: raise SourceLine(sink, sourceName, ValidationException).makeError( f"{sourceName} not found: {parm_id}" ) srcs_of_sink = [src_dict[parm_id]] linkMerge = None if sink.pickValue is not None: validation["warning"].append( SrcSink( src_dict[parm_id], sink, linkMerge, message="pickValue is used but only a single input source is declared", ) ) if _is_conditional_step(param_to_step, parm_id): src_typ = aslist(type_dict[src_dict[parm_id].id]) snk_typ = type_dict[sink.id] if "null" not in src_typ: src_typ = ["null"] + cast(list[Any], src_typ) if ( not isinstance(snk_typ, MutableSequence) or "null" not in snk_typ ): validation["warning"].append( SrcSink( src_dict[parm_id], sink, linkMerge, message="Source is from conditional step and may produce `null`", ) ) type_dict[src_dict[parm_id].id] = src_typ if _is_all_output_method_loop_step(param_to_step, parm_id): src_typ = type_dict[src_dict[parm_id].id] type_dict[src_dict[parm_id].id] = cwl.ArraySchema( items=src_typ, type_="array" ) for src in srcs_of_sink: check_result = check_types( type_dict[cast(str, src.id)], sink_type, linkMerge, getattr(sink, "valueFrom", None), ) if check_result in ("warning", "exception"): validation[check_result].append( SrcSink(src, sink, linkMerge, extra_message) ) return validation def check_types( srctype: Any, sinktype: Any, linkMerge: str | None, valueFrom: str | None = None, ) -> str: """ Check if the source and sink types are correct. Acceptable types are "pass", "warning", or "exception". """ if valueFrom is not None: return "pass" match linkMerge: case None: if can_assign_src_to_sink(srctype, sinktype, strict=True): return "pass" if can_assign_src_to_sink(srctype, sinktype, strict=False): return "warning" return "exception" case "merge_nested": return check_types( cwl.ArraySchema(items=srctype, type_="array"), sinktype, None, None, ) case "merge_flattened": return check_types(merge_flatten_type(srctype), sinktype, None, None) case _: raise ValidationException(f"Invalid value {linkMerge} for linkMerge field.") def content_limit_respected_read_bytes(f: IO[bytes]) -> bytes: """ Read file content up to 64 kB as a byte array. Throw exception for larger files (see https://www.commonwl.org/v1.2/Workflow.html#Changelog). """ contents = f.read(CONTENT_LIMIT + 1) if len(contents) > CONTENT_LIMIT: raise WorkflowException( "file is too large, loadContents limited to %d bytes" % CONTENT_LIMIT ) return contents def content_limit_respected_read(f: IO[bytes]) -> str: """ Read file content up to 64 kB as an utf-8 encoded string. Throw exception for larger files (see https://www.commonwl.org/v1.2/Workflow.html#Changelog). """ return content_limit_respected_read_bytes(f).decode("utf-8") def convert_stdstreams_to_files(clt: cwl.CommandLineTool) -> None: """Convert stdin, stdout and stderr type shortcuts to files.""" for out in clt.outputs: if out.type_ == "stdout": if out.outputBinding is not None: raise ValidationException( "Not allowed to specify outputBinding when using stdout shortcut." ) if clt.stdout is None: clt.stdout = hashlib.sha1( # nosec json_dumps(clt.save(), sort_keys=True).encode("utf-8") ).hexdigest() out.type_ = "File" out.outputBinding = cwl.CommandOutputBinding(glob=clt.stdout) elif out.type_ == "stderr": if out.outputBinding is not None: raise ValidationException( "Not allowed to specify outputBinding when using stderr shortcut." ) if clt.stderr is None: clt.stderr = hashlib.sha1( # nosec json_dumps(clt.save(), sort_keys=True).encode("utf-8") ).hexdigest() out.type_ = "File" out.outputBinding = cwl.CommandOutputBinding(glob=clt.stderr) for inp in clt.inputs: if inp.type_ == "stdin": if inp.inputBinding is not None: raise ValidationException( "Not allowed to specify unputBinding when using stdin shortcut." ) if clt.stdin is not None: raise ValidationException( "Not allowed to specify stdin path when using stdin type shortcut." ) else: clt.stdin = ( "$(inputs.%s.path)" % cast(str, inp.id).rpartition("#")[2].split("/")[-1] ) inp.type_ = "File" def load_inputfile( doc: Any, baseuri: str | None = None, loadingOptions: cwl.LoadingOptions | None = None, ) -> Any: """Load a CWL v1.2 input file from a serialized YAML string or a YAML object.""" if baseuri is None: baseuri = cwl.file_uri(str(Path.cwd())) + "/" if loadingOptions is None: loadingOptions = cwl.LoadingOptions() result, metadata = _inputfile_load( doc, baseuri, loadingOptions, ) return result def load_inputfile_by_string( string: Any, uri: str, loadingOptions: cwl.LoadingOptions | None = None, ) -> Any: """Load a CWL v1.2 input file from a serialized YAML string.""" result = yaml_no_ts().load(string) add_lc_filename(result, uri) if loadingOptions is None: loadingOptions = cwl.LoadingOptions(fileuri=uri) result, metadata = _inputfile_load( result, uri, loadingOptions, ) return result def load_inputfile_by_yaml( yaml: Any, uri: str, loadingOptions: cwl.LoadingOptions | None = None, ) -> Any: """Load a CWL v1.2 input file from a YAML object.""" add_lc_filename(yaml, uri) if loadingOptions is None: loadingOptions = cwl.LoadingOptions(fileuri=uri) result, metadata = _inputfile_load( yaml, uri, loadingOptions, ) return result def merge_flatten_type(src: Any) -> Any: """Return the merge flattened type of the source type.""" if isinstance(src, MutableSequence): return [merge_flatten_type(t) for t in src] if isinstance(src, cwl.ArraySchema): return src return cwl.ArraySchema(type_="array", items=src) def type_for_step_input( step: cwl.WorkflowStep, in_: cwl.WorkflowStepInput, ) -> Any: """Determine the type for the given step input.""" if in_.valueFrom is not None: return "Any" step_run = cwl_utils.parser.utils.load_step(step) cwl_utils.parser.utils.convert_stdstreams_to_files(step_run) if step_run and step_run.inputs: for step_input in step_run.inputs: if cast(str, step_input.id).split("#")[-1] == in_.id.split("#")[-1]: input_type = step_input.type_ if step.scatter is not None and in_.id in aslist(step.scatter): input_type = cwl.ArraySchema(items=input_type, type_="array") return input_type return "Any" def type_for_step_output( step: cwl.WorkflowStep, sourcename: str, ) -> Any: """Determine the type for the given step output.""" step_run = cwl_utils.parser.utils.load_step(step) cwl_utils.parser.utils.convert_stdstreams_to_files(step_run) if step_run and step_run.outputs: for output in step_run.outputs: if ( output.id.split("#")[-1].split("/")[-1] == sourcename.split("#")[-1].split("/")[-1] ): output_type = output.type_ if step.scatter is not None: if step.scatterMethod == "nested_crossproduct": for _ in range(len(aslist(step.scatter))): output_type = cwl.ArraySchema( items=output_type, type_="array" ) else: output_type = cwl.ArraySchema(items=output_type, type_="array") return output_type raise ValidationException( "param {} not found in {}.".format( sourcename, yaml_dumps(cwl.save(step)), ) ) def type_for_source( process: cwl.CommandLineTool | cwl.Workflow | cwl.ExpressionTool, sourcenames: str | list[str], parent: cwl.Workflow | None = None, linkMerge: str | None = None, pickValue: str | None = None, ) -> Any: """Determine the type for the given sourcenames.""" scatter_context: list[tuple[int, str] | None] = [] params = param_for_source_id(process, sourcenames, parent, scatter_context) if not isinstance(params, MutableSequence): new_type = params.type_ if scatter_context[0] is not None: if scatter_context[0][1] == "nested_crossproduct": for _ in range(scatter_context[0][0]): new_type = cwl.ArraySchema(items=new_type, type_="array") else: new_type = cwl.ArraySchema(items=new_type, type_="array") if linkMerge == "merge_nested": new_type = cwl.ArraySchema(items=new_type, type_="array") elif linkMerge == "merge_flattened": new_type = merge_flatten_type(new_type) if pickValue is not None: if isinstance(new_type, cwl.ArraySchema): if pickValue in ("first_non_null", "the_only_non_null"): new_type = new_type.items return new_type new_type = [] for p, sc in zip(params, scatter_context): if isinstance(p, str) and not any(_compare_type(t, p) for t in new_type): cur_type = p elif hasattr(p, "type_") and not any( _compare_type(t, p.type_) for t in new_type ): cur_type = p.type_ else: cur_type = None if cur_type is not None: if sc is not None: if sc[1] == "nested_crossproduct": for _ in range(sc[0]): cur_type = cwl.ArraySchema(items=cur_type, type_="array") else: cur_type = cwl.ArraySchema(items=cur_type, type_="array") new_type.append(cur_type) if len(new_type) == 1: new_type = new_type[0] if linkMerge == "merge_nested": new_type = cwl.ArraySchema(items=new_type, type_="array") elif linkMerge == "merge_flattened": new_type = merge_flatten_type(new_type) elif isinstance(sourcenames, list) and len(sourcenames) > 1: new_type = cwl.ArraySchema(items=new_type, type_="array") if pickValue is not None: if isinstance(new_type, cwl.ArraySchema): if pickValue in ("first_non_null", "the_only_non_null"): new_type = new_type.items return new_type def param_for_source_id( process: cwl.CommandLineTool | cwl.Workflow | cwl.ExpressionTool, sourcenames: str | list[str], parent: cwl.Workflow | None = None, scatter_context: list[tuple[int, str] | None] | None = None, ) -> ( cwl.CommandInputParameter | cwl.CommandOutputParameter | cwl.WorkflowInputParameter | MutableSequence[ cwl.CommandInputParameter | cwl.CommandOutputParameter | cwl.WorkflowInputParameter ] ): """Find the process input parameter that matches one of the given sourcenames.""" if isinstance(sourcenames, str): sourcenames = [sourcenames] params: MutableSequence[ cwl.CommandInputParameter | cwl.CommandOutputParameter | cwl.WorkflowInputParameter ] = [] for sourcename in sourcenames: if not isinstance(process, cwl.Workflow): for param in process.inputs: if param.id.split("#")[-1] == sourcename.split("#")[-1]: params.append(param) if scatter_context is not None: scatter_context.append(None) targets = [process] if parent: targets.append(parent) for target in targets: if isinstance(target, cwl.Workflow): for inp in target.inputs: if inp.id.split("#")[-1] == sourcename.split("#")[-1]: params.append(inp) if scatter_context is not None: scatter_context.append(None) for step in target.steps: if ( "/".join(sourcename.split("#")[-1].split("/")[:-1]) == step.id.split("#")[-1] and step.out ): step_run = cwl_utils.parser.utils.load_step(step) cwl_utils.parser.utils.convert_stdstreams_to_files(step_run) for outp in step.out: outp_id = outp if isinstance(outp, str) else outp.id if ( outp_id.split("#")[-1].split("/")[-1] == sourcename.split("#")[-1].split("/")[-1] ): if step_run and step_run.outputs: for output in step_run.outputs: if ( output.id.split("#")[-1].split("/")[-1] == sourcename.split("#")[-1].split("/")[-1] ): params.append(output) if scatter_context is not None: if scatter_context is not None: if isinstance(step.scatter, str): scatter_context.append( ( 1, step.scatterMethod or "dotproduct", ) ) elif isinstance( step.scatter, MutableSequence ): scatter_context.append( ( len(step.scatter), step.scatterMethod or "dotproduct", ) ) else: scatter_context.append(None) if len(params) == 1: return params[0] elif len(params) > 1: return params raise WorkflowException( "param {} not found in {}\n{}.".format( sourcename, yaml_dumps(cwl.save(process)), (f" or\n {yaml_dumps(cwl.save(parent))}" if parent is not None else ""), ) ) cwl_utils-0.41/cwl_utils/parser/latest.py0000644000000000000000000000010613615410400015527 0ustar00"""Convenience module.""" from .cwl_v1_2 import * # noqa: F401,F403 cwl_utils-0.41/cwl_utils/parser/utils.py0000644000000000000000000004221113615410400015376 0ustar00"""CWL parser utility functions.""" import copy import logging from collections.abc import MutableSequence from pathlib import Path from types import ModuleType from typing import Any, Optional, cast from urllib.parse import unquote_plus, urlparse from schema_salad.exceptions import ValidationException from schema_salad.sourceline import SourceLine, strip_dup_lineno from schema_salad.utils import json_dumps, yaml_no_ts import cwl_utils import cwl_utils.parser from . import ( LoadingOptions, Process, Workflow, WorkflowStep, WorkflowStepInput, cwl_v1_0, cwl_v1_0_utils, cwl_v1_1, cwl_v1_1_utils, cwl_v1_2, cwl_v1_2_utils, ) _logger = logging.getLogger("cwl_utils") def convert_stdstreams_to_files(process: Process) -> None: """Convert stdin, stdout and stderr type shortcuts to files.""" match process: case cwl_v1_0.CommandLineTool(): cwl_v1_0_utils.convert_stdstreams_to_files(process) case cwl_v1_1.CommandLineTool(): cwl_v1_1_utils.convert_stdstreams_to_files(process) case cwl_v1_2.CommandLineTool(): cwl_v1_2_utils.convert_stdstreams_to_files(process) def load_inputfile_by_uri( version: str, path: str | Path, loadingOptions: LoadingOptions | None = None, ) -> Any: """Load a CWL input file from a URI or a path.""" if isinstance(path, str): uri = urlparse(path) if not uri.scheme or uri.scheme == "file": real_path = Path(unquote_plus(uri.path)).resolve().as_uri() else: real_path = path else: real_path = path.resolve().as_uri() if version is None: raise ValidationException("could not get the cwlVersion") baseuri: str = real_path if loadingOptions is None: match version: case "v1.0": loadingOptions = cwl_v1_0.LoadingOptions(fileuri=baseuri) case "v1.1": loadingOptions = cwl_v1_1.LoadingOptions(fileuri=baseuri) case "v1.2": loadingOptions = cwl_v1_2.LoadingOptions(fileuri=baseuri) case _: raise ValidationException( f"Version error. Did not recognise {version} as a CWL version" ) doc = loadingOptions.fetcher.fetch_text(real_path) return load_inputfile_by_string(version, doc, baseuri, loadingOptions) def load_inputfile( version: str, doc: Any, baseuri: str | None = None, loadingOptions: LoadingOptions | None = None, ) -> Any: """Load a CWL input file from a serialized YAML string or a YAML object.""" if baseuri is None: baseuri = cwl_v1_0.file_uri(str(Path.cwd())) + "/" if isinstance(doc, str): return load_inputfile_by_string(version, doc, baseuri, loadingOptions) return load_inputfile_by_yaml(version, doc, baseuri, loadingOptions) def load_inputfile_by_string( version: str, string: str, uri: str, loadingOptions: LoadingOptions | None = None, ) -> Any: """Load a CWL input file from a serialized YAML string.""" result = yaml_no_ts().load(string) return load_inputfile_by_yaml(version, result, uri, loadingOptions) def load_inputfile_by_yaml( version: str, yaml: Any, uri: str, loadingOptions: LoadingOptions | None = None, ) -> Any: """Load a CWL input file from a YAML object.""" match version: case "v1.0": return cwl_v1_0_utils.load_inputfile_by_yaml( yaml, uri, cast(Optional[cwl_v1_0.LoadingOptions], loadingOptions) ) case "v1.1": return cwl_v1_1_utils.load_inputfile_by_yaml( yaml, uri, cast(Optional[cwl_v1_1.LoadingOptions], loadingOptions) ) case "v1.2": return cwl_v1_2_utils.load_inputfile_by_yaml( yaml, uri, cast(Optional[cwl_v1_2.LoadingOptions], loadingOptions) ) case None: raise ValidationException("could not get the cwlVersion") case _: raise ValidationException( f"Version error. Did not recognise {version} as a CWL version" ) def load_step( step: cwl_utils.parser.WorkflowStep, ) -> Process: if isinstance(step.run, str): step_run = cwl_utils.parser.load_document_by_uri( path=step.loadingOptions.fetcher.urljoin( base_url=cast(str, step.loadingOptions.fileuri), url=step.run, ), loadingOptions=step.loadingOptions, ) return cast(Process, step_run) return cast(Process, copy.deepcopy(step.run)) def static_checker(workflow: cwl_utils.parser.Workflow) -> None: """Check if all source and sink types of a workflow are compatible before run time.""" step_inputs = [] step_outputs = [] type_dict = {} param_to_step = {} for step in workflow.steps: if step.in_ is not None: step_inputs.extend(step.in_) param_to_step.update({s.id: step for s in step.in_}) type_dict.update( { cast(str, s.id): type_for_step_input( step, s, cast(str, workflow.cwlVersion) ) for s in step.in_ } ) if step.out is not None: # FIXME: the correct behaviour here would be to create WorkflowStepOutput directly at load time match workflow.cwlVersion: case "v1.0": step_outs = [ cwl_v1_0.WorkflowStepOutput(s) if isinstance(s, str) else s for s in step.out ] case "v1.1": step_outs = [ cwl_v1_1.WorkflowStepOutput(s) if isinstance(s, str) else s for s in step.out ] case "v1.2": step_outs = [ cwl_v1_2.WorkflowStepOutput(s) if isinstance(s, str) else s for s in step.out ] case _: raise Exception(f"Unsupported CWL version {workflow.cwlVersion}") step_outputs.extend(step_outs) param_to_step.update({s.id: step for s in step_outs}) type_dict.update( { s.id: type_for_step_output(step, s.id, workflow.cwlVersion) for s in step_outs } ) src_dict = { **{param.id: param for param in workflow.inputs}, **{param.id: param for param in step_outputs}, } type_dict = { **type_dict, **{param.id: param.type_ for param in workflow.inputs}, **{param.id: param.type_ for param in workflow.outputs}, } parser: ModuleType step_inputs_val: dict[str, Any] workflow_outputs_val: dict[str, Any] match workflow.cwlVersion: case "v1.0": parser = cwl_v1_0 step_inputs_val = cwl_v1_0_utils.check_all_types( src_dict, step_inputs, type_dict ) workflow_outputs_val = cwl_v1_0_utils.check_all_types( src_dict, workflow.outputs, type_dict ) case "v1.1": parser = cwl_v1_1 step_inputs_val = cwl_v1_1_utils.check_all_types( src_dict, step_inputs, type_dict ) workflow_outputs_val = cwl_v1_1_utils.check_all_types( src_dict, workflow.outputs, type_dict ) case "v1.2": parser = cwl_v1_2 step_inputs_val = cwl_v1_2_utils.check_all_types( src_dict, step_inputs, param_to_step, type_dict ) workflow_outputs_val = cwl_v1_2_utils.check_all_types( src_dict, workflow.outputs, param_to_step, type_dict ) case _ as cwlVersion: raise Exception(f"Unsupported CWL version {cwlVersion}") warnings = step_inputs_val["warning"] + workflow_outputs_val["warning"] exceptions = step_inputs_val["exception"] + workflow_outputs_val["exception"] warning_msgs = [] exception_msgs = [] for warning in warnings: src = warning.src sink = warning.sink linkMerge = warning.linkMerge msg = ( SourceLine(src, "type").makeError( "Source '%s' of type %s may be incompatible" % ( parser.shortname(src.id), json_dumps(parser.save(type_dict[src.id])), ) ) + "\n" + SourceLine(sink, "type").makeError( " with sink '%s' of type %s" % ( parser.shortname(sink.id), json_dumps(parser.save(type_dict[sink.id])), ) ) ) if linkMerge is not None: msg += "\n" + SourceLine(sink).makeError( " source has linkMerge method %s" % linkMerge ) if warning.message is not None: msg += "\n" + SourceLine(sink).makeError(" " + warning.message) if msg: warning_msgs.append(msg) for exception in exceptions: src = exception.src sink = exception.sink linkMerge = exception.linkMerge extra_message = exception.message msg = ( SourceLine(src, "type").makeError( "Source '%s' of type %s is incompatible" % (parser.shortname(src.id), json_dumps(parser.save(type_dict[src.id]))) ) + "\n" + SourceLine(sink, "type").makeError( " with sink '%s' of type %s" % ( parser.shortname(sink.id), json_dumps(parser.save(type_dict[sink.id])), ) ) ) if extra_message is not None: msg += "\n" + SourceLine(sink).makeError(" " + extra_message) if linkMerge is not None: msg += "\n" + SourceLine(sink).makeError( " source has linkMerge method %s" % linkMerge ) exception_msgs.append(msg) for sink in step_inputs: if ( "null" != type_dict[sink.id] and not ( isinstance(type_dict[sink.id], MutableSequence) and "null" in type_dict[sink.id] ) and getattr(sink, "source", None) is None and getattr(sink, "default", None) is None and getattr(sink, "valueFrom", None) is None ): msg = SourceLine(sink).makeError( "Required parameter '%s' does not have source, default, or valueFrom expression" % parser.shortname(sink.id) ) exception_msgs.append(msg) all_warning_msg = strip_dup_lineno("\n".join(warning_msgs)) all_exception_msg = strip_dup_lineno("\n" + "\n".join(exception_msgs)) if all_warning_msg: _logger.warning("Workflow checker warning:\n%s", all_warning_msg) if exceptions: raise ValidationException(all_exception_msg) def type_for_source( process: Process, sourcenames: str | list[str], parent: Workflow | None = None, linkMerge: str | None = None, pickValue: str | None = None, ) -> Any: """Determine the type for the given sourcenames.""" match process.cwlVersion: case "v1.0": return cwl_v1_0_utils.type_for_source( cast( cwl_v1_0.CommandLineTool | cwl_v1_0.Workflow | cwl_v1_0.ExpressionTool, process, ), sourcenames, cast(cwl_v1_0.Workflow | None, parent), linkMerge, ) case "v1.1": return cwl_v1_1_utils.type_for_source( cast( cwl_v1_1.CommandLineTool | cwl_v1_1.Workflow | cwl_v1_1.ExpressionTool, process, ), sourcenames, cast(cwl_v1_1.Workflow | None, parent), linkMerge, ) case "v1.2": return cwl_v1_2_utils.type_for_source( cast( cwl_v1_2.CommandLineTool | cwl_v1_2.Workflow | cwl_v1_2.ExpressionTool, process, ), sourcenames, cast(cwl_v1_2.Workflow | None, parent), linkMerge, pickValue, ) case None: raise ValidationException("could not get the cwlVersion") case _ as cwlVersion: raise ValidationException( f"Version error. Did not recognise {cwlVersion} as a CWL version" ) def type_for_step_input( step: WorkflowStep, in_: WorkflowStepInput, cwlVersion: str ) -> Any: """Determine the type for the given step output.""" match cwlVersion: case "v1.0": return cwl_v1_0_utils.type_for_step_input( cast(cwl_v1_0.WorkflowStep, step), cast(cwl_v1_0.WorkflowStepInput, in_) ) case "v1.1": return cwl_v1_1_utils.type_for_step_input( cast(cwl_v1_1.WorkflowStep, step), cast(cwl_v1_1.WorkflowStepInput, in_) ) case "v1.2": return cwl_v1_2_utils.type_for_step_input( cast(cwl_v1_2.WorkflowStep, step), cast(cwl_v1_2.WorkflowStepInput, in_) ) def type_for_step_output(step: WorkflowStep, sourcename: str, cwlVersion: str) -> Any: """Determine the type for the given step output.""" match cwlVersion: case "v1.0": return cwl_v1_0_utils.type_for_step_output( cast(cwl_v1_0.WorkflowStep, step), sourcename ) case "v1.1": return cwl_v1_1_utils.type_for_step_output( cast(cwl_v1_1.WorkflowStep, step), sourcename ) case "v1.2": return cwl_v1_2_utils.type_for_step_output( cast(cwl_v1_2.WorkflowStep, step), sourcename ) def param_for_source_id( process: ( cwl_utils.parser.CommandLineTool | cwl_utils.parser.Workflow | cwl_utils.parser.ExpressionTool ), sourcenames: str | list[str], parent: cwl_utils.parser.Workflow | None = None, scatter_context: list[tuple[int, str] | None] | None = None, ) -> ( ( MutableSequence[ cwl_utils.parser.cwl_v1_0.InputParameter | cwl_utils.parser.cwl_v1_0.CommandOutputParameter ] | cwl_utils.parser.cwl_v1_0.InputParameter | cwl_utils.parser.cwl_v1_0.CommandOutputParameter ) | ( MutableSequence[ cwl_utils.parser.cwl_v1_1.CommandInputParameter | cwl_utils.parser.cwl_v1_1.CommandOutputParameter | cwl_utils.parser.cwl_v1_1.WorkflowInputParameter ] | cwl_utils.parser.cwl_v1_1.CommandInputParameter | cwl_utils.parser.cwl_v1_1.CommandOutputParameter | cwl_utils.parser.cwl_v1_1.WorkflowInputParameter ) | ( MutableSequence[ cwl_utils.parser.cwl_v1_2.CommandInputParameter | cwl_utils.parser.cwl_v1_2.CommandOutputParameter | cwl_utils.parser.cwl_v1_2.WorkflowInputParameter ] | cwl_utils.parser.cwl_v1_2.CommandInputParameter | cwl_utils.parser.cwl_v1_2.CommandOutputParameter | cwl_utils.parser.cwl_v1_2.WorkflowInputParameter ) ): match process.cwlVersion: case "v1.0": return cwl_utils.parser.cwl_v1_0_utils.param_for_source_id( cast( cwl_utils.parser.cwl_v1_0.CommandLineTool | cwl_utils.parser.cwl_v1_0.Workflow | cwl_utils.parser.cwl_v1_0.ExpressionTool, process, ), sourcenames, cast(cwl_utils.parser.cwl_v1_0.Workflow, parent), scatter_context, ) case "v1.1": return cwl_utils.parser.cwl_v1_1_utils.param_for_source_id( cast( cwl_utils.parser.cwl_v1_1.CommandLineTool | cwl_utils.parser.cwl_v1_1.Workflow | cwl_utils.parser.cwl_v1_1.ExpressionTool, process, ), sourcenames, cast(cwl_utils.parser.cwl_v1_1.Workflow, parent), scatter_context, ) case "v1.2": return cwl_utils.parser.cwl_v1_2_utils.param_for_source_id( cast( cwl_utils.parser.cwl_v1_2.CommandLineTool | cwl_utils.parser.cwl_v1_2.Workflow | cwl_utils.parser.cwl_v1_2.ExpressionTool, process, ), sourcenames, cast(cwl_utils.parser.cwl_v1_2.Workflow, parent), scatter_context, ) case None: raise ValidationException("could not get the cwlVersion") case _: raise ValidationException( f"Version error. Did not recognise {process.cwlVersion} as a CWL version" ) cwl_utils-0.41/cwl_utils/templates/WorkflowInputJsonSchemaTemplate.md0000644000000000000000000016347513615410400023231 0ustar00# Generating the Workflow Input JSON Schema Template * [Generating the Workflow Input JSON Schema Template](#generating-the-workflow-input-json-schema-template) * [Part 1 - Clone the CWL-TS-Auto directory](#part-1---clone-the-cwl-ts-auto-directory) * [Part 2 - Install the typescript-json-schema package](#part-2---install-the-typescript-json-schema-package) * [Part 3 - Generate the Workflow Input JSON Schema Template](#part-3---generate-the-workflow-input-json-schema-template) * [Part 4 - Refine the template with the following python script](#part-4---refine-the-template-with-the-following-python-script) * [Part 5 - Run schema generation against all tests in the cwl v1.2 directory](#part-5---run-schema-generation-against-all-tests-in-the-cwl-v12-directory) ## Part 1 - Clone the CWL-TS-Auto directory ``` git clone https://github.com/common-workflow-lab/cwl-ts-auto cd cwl-ts-auto ``` ## Part 2 - Install the typescript-json-schema package ``` npm install typescript-json-schema@^0.62.0 ``` ## Part 3 - Generate the Workflow Input JSON Schema Template ```bash npx typescript-json-schema \ --required \ --noExtraProps \ tsconfig.json \ WorkflowInputParameter > workflow_input_json_schema_template.primary.json ``` ## Part 4 - Refine the template with the following python script
Click to expand! ```python #!/usr/bin/env python3 import json from copy import deepcopy from itertools import chain from pathlib import Path from typing import Dict, List, Any import sys CLEANED_FILE_DEFINITION = { "File": { "additionalProperties": False, "description": "Represents a file (or group of files when `secondaryFiles` is provided) that\nwill be accessible by tools using standard POSIX file system call API such as\nopen(2) and read(2).\n\nFiles are represented as objects with `class` of `File`. File objects have\na number of properties that provide metadata about the file.\n\nThe `location` property of a File is a URI that uniquely identifies the\nfile. Implementations must support the `file://` URI scheme and may support\nother schemes such as `http://` and `https://`. The value of `location` may also be a\nrelative reference, in which case it must be resolved relative to the URI\nof the document it appears in. Alternately to `location`, implementations\nmust also accept the `path` property on File, which must be a filesystem\npath available on the same host as the CWL runner (for inputs) or the\nruntime environment of a command line tool execution (for command line tool\noutputs).\n\nIf no `location` or `path` is specified, a file object must specify\n`contents` with the UTF-8 text content of the file. This is a \"file\nliteral\". File literals do not correspond to external resources, but are\ncreated on disk with `contents` with when needed for executing a tool.\nWhere appropriate, expressions can return file literals to define new files\non a runtime. The maximum size of `contents` is 64 kilobytes.\n\nThe `basename` property defines the filename on disk where the file is\nstaged. This may differ from the resource name. If not provided,\n`basename` must be computed from the last path part of `location` and made\navailable to expressions.\n\nThe `secondaryFiles` property is a list of File or Directory objects that\nmust be staged in the same directory as the primary file. It is an error\nfor file names to be duplicated in `secondaryFiles`.\n\nThe `size` property is the size in bytes of the File. It must be computed\nfrom the resource and made available to expressions. The `checksum` field\ncontains a cryptographic hash of the file content for use it verifying file\ncontents. Implementations may, at user option, enable or disable\ncomputation of the `checksum` field for performance or other reasons.\nHowever, the ability to compute output checksums is required to pass the\nCWL conformance test suite.\n\nWhen executing a CommandLineTool, the files and secondary files may be\nstaged to an arbitrary directory, but must use the value of `basename` for\nthe filename. The `path` property must be file path in the context of the\ntool execution runtime (local to the compute node, or within the executing\ncontainer). All computed properties should be available to expressions.\nFile literals also must be staged and `path` must be set.\n\nWhen collecting CommandLineTool outputs, `glob` matching returns file paths\n(with the `path` property) and the derived properties. This can all be\nmodified by `outputEval`. Alternately, if the file `cwl.output.json` is\npresent in the output, `outputBinding` is ignored.\n\nFile objects in the output must provide either a `location` URI or a `path`\nproperty in the context of the tool execution runtime (local to the compute\nnode, or within the executing container).\n\nWhen evaluating an ExpressionTool, file objects must be referenced via\n`location` (the expression tool does not have access to files on disk so\n`path` is meaningless) or as file literals. It is legal to return a file\nobject with an existing `location` but a different `basename`. The\n`loadContents` field of ExpressionTool inputs behaves the same as on\nCommandLineTool inputs, however it is not meaningful on the outputs.\n\nAn ExpressionTool may forward file references from input to output by using\nthe same value for `location`.", "properties": { "basename": { "description": "The base name of the file, that is, the name of the file without any\nleading directory path. The base name must not contain a slash `/`.\n\nIf not provided, the implementation must set this field based on the\n`location` field by taking the final path component after parsing\n`location` as an IRI. If `basename` is provided, it is not required to\nmatch the value from `location`.\n\nWhen this file is made available to a CommandLineTool, it must be named\nwith `basename`, i.e. the final component of the `path` field must match\n`basename`.", "type": "string" }, "checksum": { "description": "Optional hash code for validating file integrity. Currently, must be in the form\n\"sha1$ + hexadecimal string\" using the SHA-1 algorithm.", "type": "string" }, "class": { "const": "File", "description": "Must be `File` to indicate this object describes a file.", "type": "string" }, "contents": { "description": "File contents literal.\n\nIf neither `location` nor `path` is provided, `contents` must be\nnon-null. The implementation must assign a unique identifier for the\n`location` field. When the file is staged as input to CommandLineTool,\nthe value of `contents` must be written to a file.\n\nIf `contents` is set as a result of a Javascript expression,\nan `entry` in `InitialWorkDirRequirement`, or read in from\n`cwl.output.json`, there is no specified upper limit on the\nsize of `contents`. Implementations may have practical limits\non the size of `contents` based on memory and storage\navailable to the workflow runner or other factors.\n\nIf the `loadContents` field of an `InputParameter` or\n`OutputParameter` is true, and the input or output File object\n`location` is valid, the file must be a UTF-8 text file 64 KiB\nor smaller, and the implementation must read the entire\ncontents of the file and place it in the `contents` field. If\nthe size of the file is greater than 64 KiB, the\nimplementation must raise a fatal error.", "type": "string" }, "dirname": { "description": "The name of the directory containing file, that is, the path leading up\nto the final slash in the path such that `dirname + '/' + basename ==\npath`.\n\nThe implementation must set this field based on the value of `path`\nprior to evaluating parameter references or expressions in a\nCommandLineTool document. This field must not be used in any other\ncontext.", "type": "string" }, "format": { "description": "The format of the file: this must be an IRI of a concept node that\nrepresents the file format, preferably defined within an ontology.\nIf no ontology is available, file formats may be tested by exact match.\n\nReasoning about format compatibility must be done by checking that an\ninput file format is the same, `owl:equivalentClass` or\n`rdfs:subClassOf` the format required by the input parameter.\n`owl:equivalentClass` is transitive with `rdfs:subClassOf`, e.g. if\n` owl:equivalentClass ` and ` owl:subclassOf ` then infer\n` owl:subclassOf `.\n\nFile format ontologies may be provided in the \"$schemas\" metadata at the\nroot of the document. If no ontologies are specified in `$schemas`, the\nruntime may perform exact file format matches.", "type": "string" }, "location": { "description": "An IRI that identifies the file resource. This may be a relative\nreference, in which case it must be resolved using the base IRI of the\ndocument. The location may refer to a local or remote resource; the\nimplementation must use the IRI to retrieve file content. If an\nimplementation is unable to retrieve the file content stored at a\nremote resource (due to unsupported protocol, access denied, or other\nissue) it must signal an error.\n\nIf the `location` field is not provided, the `contents` field must be\nprovided. The implementation must assign a unique identifier for\nthe `location` field.\n\nIf the `path` field is provided but the `location` field is not, an\nimplementation may assign the value of the `path` field to `location`,\nthen follow the rules above.", "type": "string" }, "nameext": { "description": "The basename extension such that `nameroot + nameext == basename`, and\n`nameext` is empty or begins with a period and contains at most one\nperiod. Leading periods on the basename are ignored; a basename of\n`.cshrc` will have an empty `nameext`.\n\nThe implementation must set this field automatically based on the value\nof `basename` prior to evaluating parameter references or expressions.", "type": "string" }, "nameroot": { "description": "The basename root such that `nameroot + nameext == basename`, and\n`nameext` is empty or begins with a period and contains at most one\nperiod. For the purposes of path splitting leading periods on the\nbasename are ignored; a basename of `.cshrc` will have a nameroot of\n`.cshrc`.\n\nThe implementation must set this field automatically based on the value\nof `basename` prior to evaluating parameter references or expressions.", "type": "string" }, "path": { "description": "The local host path where the File is available when a CommandLineTool is\nexecuted. This field must be set by the implementation. The final\npath component must match the value of `basename`. This field\nmust not be used in any other context. The command line tool being\nexecuted must be able to access the file at `path` using the POSIX\n`open(2)` syscall.\n\nAs a special case, if the `path` field is provided but the `location`\nfield is not, an implementation may assign the value of the `path`\nfield to `location`, and remove the `path` field.\n\nIf the `path` contains [POSIX shell metacharacters](http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_02)\n(`|`,`&`, `;`, `<`, `>`, `(`,`)`, `$`,`` ` ``, `\\`, `\"`, `'`,\n``, ``, and ``) or characters\n[not allowed](http://www.iana.org/assignments/idna-tables-6.3.0/idna-tables-6.3.0.xhtml)\nfor [Internationalized Domain Names for Applications](https://tools.ietf.org/html/rfc6452)\nthen implementations may terminate the process with a\n`permanentFailure`.", "type": "string" }, "secondaryFiles": { "description": "A list of additional files or directories that are associated with the\nprimary file and must be transferred alongside the primary file.\nExamples include indexes of the primary file, or external references\nwhich must be included when loading primary document. A file object\nlisted in `secondaryFiles` may itself include `secondaryFiles` for\nwhich the same rules apply.", "items": { "anyOf": [ { "$ref": "#/definitions/File" }, { "$ref": "#/definitions/Directory" } ] }, "type": "array" }, "size": { "description": "Optional file size (in bytes)", "type": "number" } }, "required": [ "class" ], "type": "object" } } CLEANED_DIRECTORY_DEFINITION = { "Directory": { "additionalProperties": False, "description": "Represents a directory to present to a command line tool.\n\nDirectories are represented as objects with `class` of `Directory`. Directory objects have\na number of properties that provide metadata about the directory.\n\nThe `location` property of a Directory is a URI that uniquely identifies\nthe directory. Implementations must support the file:// URI scheme and may\nsupport other schemes such as http://. Alternately to `location`,\nimplementations must also accept the `path` property on Directory, which\nmust be a filesystem path available on the same host as the CWL runner (for\ninputs) or the runtime environment of a command line tool execution (for\ncommand line tool outputs).\n\nA Directory object may have a `listing` field. This is a list of File and\nDirectory objects that are contained in the Directory. For each entry in\n`listing`, the `basename` property defines the name of the File or\nSubdirectory when staged to disk. If `listing` is not provided, the\nimplementation must have some way of fetching the Directory listing at\nruntime based on the `location` field.\n\nIf a Directory does not have `location`, it is a Directory literal. A\nDirectory literal must provide `listing`. Directory literals must be\ncreated on disk at runtime as needed.\n\nThe resources in a Directory literal do not need to have any implied\nrelationship in their `location`. For example, a Directory listing may\ncontain two files located on different hosts. It is the responsibility of\nthe runtime to ensure that those files are staged to disk appropriately.\nSecondary files associated with files in `listing` must also be staged to\nthe same Directory.\n\nWhen executing a CommandLineTool, Directories must be recursively staged\nfirst and have local values of `path` assigned.\n\nDirectory objects in CommandLineTool output must provide either a\n`location` URI or a `path` property in the context of the tool execution\nruntime (local to the compute node, or within the executing container).\n\nAn ExpressionTool may forward file references from input to output by using\nthe same value for `location`.\n\nName conflicts (the same `basename` appearing multiple times in `listing`\nor in any entry in `secondaryFiles` in the listing) is a fatal error.", "properties": { "basename": { "description": "The base name of the directory, that is, the name of the file without any\nleading directory path. The base name must not contain a slash `/`.\n\nIf not provided, the implementation must set this field based on the\n`location` field by taking the final path component after parsing\n`location` as an IRI. If `basename` is provided, it is not required to\nmatch the value from `location`.\n\nWhen this file is made available to a CommandLineTool, it must be named\nwith `basename`, i.e. the final component of the `path` field must match\n`basename`.", "type": "string" }, "class": { "const": "Directory", "description": "Must be `Directory` to indicate this object describes a Directory.", "type": "string" }, "listing": { "description": "List of files or subdirectories contained in this directory. The name\nof each file or subdirectory is determined by the `basename` field of\neach `File` or `Directory` object. It is an error if a `File` shares a\n`basename` with any other entry in `listing`. If two or more\n`Directory` object share the same `basename`, this must be treated as\nequivalent to a single subdirectory with the listings recursively\nmerged.", "items": { "anyOf": [ { "$ref": "#/definitions/File" }, { "$ref": "#/definitions/Directory" } ] }, "type": "array" }, "location": { "description": "An IRI that identifies the directory resource. This may be a relative\nreference, in which case it must be resolved using the base IRI of the\ndocument. The location may refer to a local or remote resource. If\nthe `listing` field is not set, the implementation must use the\nlocation IRI to retrieve directory listing. If an implementation is\nunable to retrieve the directory listing stored at a remote resource (due to\nunsupported protocol, access denied, or other issue) it must signal an\nerror.\n\nIf the `location` field is not provided, the `listing` field must be\nprovided. The implementation must assign a unique identifier for\nthe `location` field.\n\nIf the `path` field is provided but the `location` field is not, an\nimplementation may assign the value of the `path` field to `location`,\nthen follow the rules above.", "type": "string" }, "path": { "description": "The local path where the Directory is made available prior to executing a\nCommandLineTool. This must be set by the implementation. This field\nmust not be used in any other context. The command line tool being\nexecuted must be able to access the directory at `path` using the POSIX\n`opendir(2)` syscall.\n\nIf the `path` contains [POSIX shell metacharacters](http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_02)\n(`|`,`&`, `;`, `<`, `>`, `(`,`)`, `$`,`` ` ``, `\\`, `\"`, `'`,\n``, ``, and ``) or characters\n[not allowed](http://www.iana.org/assignments/idna-tables-6.3.0/idna-tables-6.3.0.xhtml)\nfor [Internationalized Domain Names for Applications](https://tools.ietf.org/html/rfc6452)\nthen implementations may terminate the process with a\n`permanentFailure`.", "type": "string" } }, "required": [ "class" ], "type": "object" } } CLEANED_ANY_DEFINITION = { "Any": { "description": "A placeholder for any type of CWL object.", "anyOf": [ { "type": "boolean" }, { "type": "integer" }, { "type": "number" }, { "type": "string" }, { "type": "array" }, { "type": "object" }, { "$ref": "#/definitions/File" }, { "$ref": "#/definitions/Directory" } ], "properties": dict( map( lambda iter_: (iter_, True), list( set( list(CLEANED_DIRECTORY_DEFINITION["Directory"]["properties"].keys()) + list(CLEANED_FILE_DEFINITION["File"]["properties"].keys()) ) ) ) ) } } DEFINTIIONS_TO_REMOVE = ["DefaultFetcher", "Dictionary", "Dictionary", "Fetcher", "T"] def remove_loading_options_and_extension_fields_from_schema(schema_dict: Any) -> Dict: """ Remove loadingOptions from schema recursively :param schema_dict: :return: """ new_schema_dict = {} if isinstance(schema_dict, Dict): for key, value in deepcopy(schema_dict).items(): if isinstance(value, Dict): if "loadingOptions" in value: del value["loadingOptions"] if "LoadingOptions" in value: del value["LoadingOptions"] if "extensionFields" in value: del value["extensionFields"] new_schema_dict[key] = remove_loading_options_and_extension_fields_from_schema(value) elif isinstance(value, List): if "loadingOptions" in value: _ = value.pop(value.index("loadingOptions")) if "LoadingOptions" in value: _ = value.pop(value.index("LoadingOptions")) if "extensionFields" in value: _ = value.pop(value.index("extensionFields")) new_schema_dict[key] = remove_loading_options_and_extension_fields_from_schema(value) else: new_schema_dict[key] = value elif isinstance(schema_dict, List): new_schema_dict = list( map(lambda value_iter: remove_loading_options_and_extension_fields_from_schema(value_iter), schema_dict)) else: # Item is a list of number new_schema_dict = schema_dict return new_schema_dict def read_schema_in_from_file(file_path: Path) -> Dict: """ Read in the auto-generated schema from the file :param file_path: :return: """ if not file_path.exists(): raise FileNotFoundError(f"File {file_path} does not exist") with open(file_path, "r") as file_h: return json.load(file_h) def assert_definitions_key(schema_dict: Dict): """ Ensure that the definitions key is part of the schema dictionary and is itself is a dictionary :param schema_dict: :return: """ if "definitions" not in schema_dict.keys() and not isinstance(schema_dict["definitions"], Dict): raise ValueError("Schema does not contain a 'definitions' key or 'definitions' is not a dictionary") def add_import_and_include_to_schema(schema_dict) -> Dict: """ Under the definitions section, add in the $import and $include definitions Copied from https://github.com/common-workflow-language/cwl-v1.2/blob/76bdf9b55e2378432e0e6380ccedebb4a94ce483/json-schema/cwl.yaml#L57-L72 { "CWLImportManual": { "description": \"\"\" Represents an '$import' directive that should point toward another compatible CWL file to import where specified. The contents of the imported file should be relevant contextually where it is being imported \"\"\", "$comment": \"\"\" The schema validation of the CWL will not itself perform the '$import' to resolve and validate its contents. Therefore, the complete schema will not be validated entirely, and could still be partially malformed. To ensure proper and exhaustive validation of a CWL definition with this schema, all '$import' directives should be resolved and extended beforehand. \"\"\", "type": "object", "properties": { "$import": { "type": "string" } }, "required": [ "$import" ], "additionalProperties": false } } Ditto for $include directive { "CWLIncludeManual": { "description": " Represents an '$include' directive that should point toward another compatible CWL file to import where specified. The contents of the imported file should be relevant contextually where it is being imported ", "$comment": " The schema validation of the CWL will not itself perform the '$include' to resolve and validate its contents. Therefore, the complete schema will not be validated entirely, and could still be partially malformed. To ensure proper and exhaustive validation of a CWL definition with this schema, all '$include' directives should be resolved and extended beforehand. ", "type": "object", "properties": { "$include": { "type": "string" } }, "required": [ "$include" ], "additionalProperties": false } } :param schema_dict: :return: """ # Always do a deepcopy on the input schema_dict = deepcopy(schema_dict) # Confirm definitions key assert_definitions_key(schema_dict) # Add in the $import and $include to the definitions schema_dict["definitions"].update( { "CWLImportManual": { "description": "" "Represents an '$import' directive that should point toward another compatible " "CWL file to import where specified. The contents of the imported file should be " "relevant contextually where it is being imported", "$comment": "" "The schema validation of the CWL will not itself perform the '$import' to resolve and " "validate its contents. Therefore, the complete schema will not be validated entirely, " "and could still be partially malformed. " "To ensure proper and exhaustive validation of a CWL definition with this schema, " "all '$import' directives should be resolved and extended beforehand", "type": "object", "properties": { "$import": { "type": "string" } }, "required": [ "$import" ], "additionalProperties": False }, "CWLIncludeManual": { "description": "" "Represents an '$include' directive that should point toward another compatible " "CWL file to import where specified. The contents of the imported file should be " "relevant contextually where it is being imported", "$comment": "" "The schema validation of the CWL will not itself perform the '$include' to resolve and " "validate its contents. Therefore, the complete schema will not be validated entirely, " "and could still be partially malformed. " "To ensure proper and exhaustive validation of a CWL definition with this schema, " "all '$include' directives should be resolved and extended beforehand", "type": "object", "properties": { "$include": { "type": "string" } }, "required": [ "$include" ], "additionalProperties": False } } ) return schema_dict def fix_inline_javascript_requirement(schema_dict: Dict) -> Dict: """ Fix the InlineJavascriptRequirement.expressionLib array to allow for $include FROM { "InlineJavascriptRequirement": { "additionalProperties": false, "description": "Auto-generated class implementation for https://w3id.org/cwl/cwl#InlineJavascriptRequirement\n\nIndicates that the workflow platform must support inline Javascript expressions.\nIf this requirement is not present, the workflow platform must not perform expression\ninterpolation.", "properties": { "class": { "const": "InlineJavascriptRequirement", "description": "Always 'InlineJavascriptRequirement'", "type": "string" }, "expressionLib": { "description": "Additional code fragments that will also be inserted\nbefore executing the expression code. Allows for function definitions that may\nbe called from CWL expressions.", "items": { "type": "string" }, "type": "array" }, "extensionFields": { "$ref": "#/definitions/Dictionary" }, "loadingOptions": { "$ref": "#/definitions/LoadingOptions" } }, "required": [ "class" ], "type": "object" } } TO { "InlineJavascriptRequirement": { "additionalProperties": false, "description": "Auto-generated class implementation for https://w3id.org/cwl/cwl#InlineJavascriptRequirement\n\nIndicates that the workflow platform must support inline Javascript expressions.\nIf this requirement is not present, the workflow platform must not perform expression\ninterpolation.", "properties": { "class": { "const": "InlineJavascriptRequirement", "description": "Always 'InlineJavascriptRequirement'", "type": "string" }, "expressionLib": { "description": "Additional code fragments that will also be inserted\nbefore executing the expression code. Allows for function definitions that may\nbe called from CWL expressions.", "items": { "anyOf": [ { "type": "string" }, { "$ref": "#/definitions/CWLIncludeManual" } ] }, "type": "array" }, "extensionFields": { "$ref": "#/definitions/Dictionary" } }, "required": [ "class" ], "type": "object" } } """ # Always do a deepcopy on the input schema_dict = deepcopy(schema_dict) # Confirm definitions key assert_definitions_key(schema_dict) # Assert InlineJavascriptRequirement exists in definitions if "InlineJavascriptRequirement" not in schema_dict["definitions"]: raise ValueError("Schema does not contain an 'InlineJavascriptRequirement' key in 'definitions'") # Confirm that the InlineJavascriptRequirement has a properties key and the properties key is a dictionary if ( "properties" not in schema_dict["definitions"]["InlineJavascriptRequirement"] or not isinstance(schema_dict["definitions"]["InlineJavascriptRequirement"]["properties"], Dict) ): raise ValueError( "Schema does not contain a 'properties' key in 'InlineJavascriptRequirement.definitions' " "or 'properties' is not a dictionary" ) # Confirm that properties has an expressionLib key if "expressionLib" not in schema_dict["definitions"]["InlineJavascriptRequirement"]["properties"]: raise ValueError("Schema does not contain an 'expressionLib' key in 'InlineJavascriptRequirement.properties'") # Confirm that expressionLib is of type array and has an items key if ( "type" not in schema_dict["definitions"]["InlineJavascriptRequirement"]["properties"]["expressionLib"] or not schema_dict["definitions"]["InlineJavascriptRequirement"]["properties"]["expressionLib"][ "type"] == "array" or "items" not in schema_dict["definitions"]["InlineJavascriptRequirement"]["properties"]["expressionLib"] ): raise ValueError( "Schema does not contain an 'expressionLib' key in 'InlineJavascriptRequirement.properties' " "of type array with an 'items' key" ) # Allow for $include in the expressionLib array by updating the the expressionLib items to be a anyOf array schema_dict["definitions"]["InlineJavascriptRequirement"]["properties"]["expressionLib"]["items"] = { "anyOf": [ { "type": "string" }, { "$ref": "#/definitions/CWLIncludeManual" } ] } return schema_dict def fix_schema_def_requirement(schema_dict: Dict) -> Dict: """ Allow SchemaDefRequirement.types array to be $import type FROM { "SchemaDefRequirement": { "additionalProperties": false, "description": "" "Auto-generated class implementation for https://w3id.org/cwl/cwl#SchemaDefRequirement" "This field consists of an array of type definitions which must be used when" "interpreting the `inputs` and `outputs` fields. When a `type` field" "contains a IRI, the implementation must check if the type is defined in" "`schemaDefs` and use that definition. If the type is not found in" "`schemaDefs`, it is an error. The entries in `schemaDefs` must be" "processed in the order listed such that later schema definitions may refer" "to earlier schema definitions." "- **Type definitions are allowed for `enum` and `record` types only.**" "- Type definitions may be shared by defining them in a file and then" " `$include`-ing them in the `types` field.\n- A file can contain a list of type definitions", "properties": { "class": { "const": "SchemaDefRequirement", "description": "Always 'SchemaDefRequirement'", "type": "string" }, "extensionFields": { "$ref": "#/definitions/Dictionary" }, "loadingOptions": { "$ref": "#/definitions/LoadingOptions" }, "types": { "description": "The list of type definitions.", "items": { "anyOf": [ { "$ref": "#/definitions/CommandInputArraySchema" }, { "$ref": "#/definitions/CommandInputRecordSchema" }, { "$ref": "#/definitions/CommandInputEnumSchema" } ] }, "type": "array" } }, "required": [ "class", "types" ], "type": "object" } } TO { "SchemaDefRequirement": { "additionalProperties": false, "description": "" "Auto-generated class implementation for https://w3id.org/cwl/cwl#SchemaDefRequirement" "This field consists of an array of type definitions which must be used when" "interpreting the `inputs` and `outputs` fields. When a `type` field" "contains a IRI, the implementation must check if the type is defined in" "`schemaDefs` and use that definition. If the type is not found in" "`schemaDefs`, it is an error. The entries in `schemaDefs` must be" "processed in the order listed such that later schema definitions may refer" "to earlier schema definitions." "- **Type definitions are allowed for `enum` and `record` types only.**" "- Type definitions may be shared by defining them in a file and then" " `$include`-ing them in the `types` field.\n- A file can contain a list of type definitions", "properties": { "class": { "const": "SchemaDefRequirement", "description": "Always 'SchemaDefRequirement'", "type": "string" }, "extensionFields": { "$ref": "#/definitions/Dictionary" }, "loadingOptions": { "$ref": "#/definitions/LoadingOptions" }, "types": { "description": "The list of type definitions.", "items": { "anyOf": [ { "$ref": "#/definitions/CommandInputArraySchema" }, { "$ref": "#/definitions/CommandInputRecordSchema" }, { "$ref": "#/definitions/CommandInputEnumSchema" }, { "$ref": "#/definitions/CWLImportManual" } ] }, "type": "array" } }, "required": [ "class", "types" ], "type": "object" } } :param schema_dict: :return: """ # Always do a deepcopy on the input schema_dict = deepcopy(schema_dict) # Confirm definitions key assert_definitions_key(schema_dict) # Assert SchemaDefRequirement exists in definitions if "SchemaDefRequirement" not in schema_dict["definitions"]: raise ValueError("Schema does not contain an 'SchemaDefRequirement' key in 'definitions'") # Confirm that the SchemaDefRequirement has a properties key and the properties key is a dictionary if ( "properties" not in schema_dict["definitions"]["SchemaDefRequirement"] or not isinstance(schema_dict["definitions"]["SchemaDefRequirement"]["properties"], Dict) ): raise ValueError( "Schema does not contain a 'properties' key in 'SchemaDefRequirement.definitions' " "or 'properties' is not a dictionary" ) # Confirm that properties has a types key if "types" not in schema_dict["definitions"]["SchemaDefRequirement"]["properties"]: raise ValueError("Schema does not contain an 'types' key in 'SchemaDefRequirement.properties'") # Confirm that types is of type array and has an items key if ( "type" not in schema_dict["definitions"]["SchemaDefRequirement"]["properties"]["types"] or not schema_dict["definitions"]["SchemaDefRequirement"]["properties"]["types"]["type"] == "array" or "items" not in schema_dict["definitions"]["SchemaDefRequirement"]["properties"]["types"] ): raise ValueError( "Schema does not contain an 'types' key in 'SchemaDefRequirement.properties' " "of type array with an 'items' key" ) # Confirm that the types items has an anyOf key and the anyOf key is an array if ( "anyOf" not in schema_dict["definitions"]["SchemaDefRequirement"]["properties"]["types"]["items"] or not isinstance(schema_dict["definitions"]["SchemaDefRequirement"]["properties"]["types"]["items"]["anyOf"], List) ): raise ValueError( "Schema does not contain an 'anyOf' key in 'SchemaDefRequirement.properties.types.items' " "or 'anyOf' is not a list" ) # Allow for $import in the types array by updating the types items to be a anyOf array schema_dict["definitions"]["SchemaDefRequirement"]["properties"]["types"]["items"]["anyOf"].append( { "$ref": "#/definitions/CWLImportManual" } ) return schema_dict def add_cwl_metadata_to_schema(schema_dict: Dict) -> Dict: """ Add in the CWL metadata to the schema Derived from https://github.com/common-workflow-language/cwl-v1.2/blob/76bdf9b55e2378432e0e6380ccedebb4a94ce483/json-schema/cwl.yaml#L2231-L2241 :param schema_dict: :return: """ # Always do a deepcopy on the input schema_dict = deepcopy(schema_dict) # Assert defintions assert_definitions_key(schema_dict) # Add in the CWL metadata to the definitions schema_dict["definitions"].update( { "CWLDocumentMetadata": { "description": "Metadata for a CWL document", "type": "object", "properties": { "$namespaces": { "description": "The namespaces used in the document", "type": "object", "patternProperties": { "^[_a-zA-Z][a-zA-Z0-9_-]*$": { "type": "string" } } }, "$schemas": { "description": "The schemas used in the document", "type": "array", "items": { "type": "string" } } }, "patternProperties": { "^s:.*$": { "type": "object" }, # Or the full version "^https://schema.org/.*$": { "type": "object" } }, "additionalProperties": False, "required": [] } } ) return schema_dict def write_schema_out_to_file(schema_dict: Dict, file_path: Path): """ Write out the schema to the file :param schema_dict: :param file_path: :return: """ with open(file_path, "w") as file_h: json.dump(schema_dict, file_h, indent=4) def rename_all_keys_with_trailing_underscore(schema_dict: Any) -> Dict: """ Keys such as class_, type_ etc. are renames from TypeScript. We need to rename them in the JSON schema back to their original names to generate a valid CWL JSON schema :param schema_dict: :return: """ new_schema_dict = {} if isinstance(schema_dict, Dict): for key, value in deepcopy(schema_dict).items(): key = key.rstrip("_") if isinstance(value, Dict): new_schema_dict[key] = rename_all_keys_with_trailing_underscore(value) elif isinstance(value, List): new_schema_dict[key] = rename_all_keys_with_trailing_underscore(value) else: new_schema_dict[key] = value elif isinstance(schema_dict, List): new_schema_dict = list( map(lambda value_iter: rename_all_keys_with_trailing_underscore(value_iter), schema_dict)) else: # Item is a value new_schema_dict = schema_dict.rstrip("_") return new_schema_dict def add_cwl_file(schema_dict: Dict) -> Dict: """ Large updates to the actual file body Can come in two forms, File and Graph. In File form, can be of type Workflow, ExpressionTool or CommandLineTool, In Graph form, we have the $graph property which then has elements of type CWLFile Both can have the metadata objects such as $namespaces and $schemas We initialise both objects. Then state that the file can be a file or a graph :param schema_dict: :return: """ # Always deep copy the input schema_dict = deepcopy(schema_dict) # Assert $ref key if "$ref" not in schema_dict: raise ValueError("Schema does not contain a '$ref' key") # Assert $ref value is "#/definitions/Workflow" if schema_dict["$ref"] != "#/definitions/Workflow": raise ValueError("Schema does not contain a '$ref' value of '#/definitions/Workflow'") # Update the schema to use 'if-else' for CommandlineTool and Expression schema_dict.update( { "$ref": "#/definitions/CWLFile", } ) schema_dict["definitions"].update( { # First create the yaml option # Which is either a workflow, commandline tool or expression tool "CWLFile": { "type": "object", "additionalProperties": False, "allOf": [ { "oneOf": [ { "$ref": "#/definitions/Workflow" }, { "$ref": "#/definitions/CommandLineTool" }, { "$ref": "#/definitions/ExpressionTool" } ] }, { "oneOf": [ { "$ref": "#/definitions/CWLDocumentMetadata" } ] } ] } } ) return schema_dict def add_cwl_graph(schema_dict: Dict) -> Dict: """ Large updates to the actual file body Can come in two forms, File and Graph. In File form, can be of type Workflow, ExpressionTool or CommandLineTool, In Graph form, we have the $graph property which then has elements of type CWLFile Both can have the metadata objects such as $namespaces and $schemas We initialise both objects. Then state that the file can be a file or a graph :param schema_dict: :return: """ # Always deep copy the input schema_dict = deepcopy(schema_dict) # Assert $ref key if "$ref" not in schema_dict: raise ValueError("Schema does not contain a '$ref' key") # Update the schema schema_dict.update( { "$ref": "#/definitions/CWLGraphWithMetadata", } ) # Update definitions schema_dict["definitions"].update( { # Now create the graph option "CWLGraph": { "type": "object", "properties": { "$graph": { "type": "array", "items": { "$ref": "#/definitions/CWLFile" } }, # Copy from Workflow "cwlVersion": schema_dict["definitions"]["Workflow"]["properties"]["cwlVersion"] }, "required": [ "$graph" ] }, "CWLGraphWithMetadata": { "type": "object", "additionalProperties": False, "allOf": [ { "$ref": "#/definitions/CWLGraph" }, { "$ref": "#/definitions/CWLDocumentMetadata" } ] } } ) return schema_dict def fix_descriptions(schema_dict: Dict) -> Dict: """ Fix the descriptions for all definitions by removing the 'Auto-generated' class implementation ... Means that users will see helpful descriptions in the schema :param schema_dict: :return: """ # Always deep copy the input schema_dict = deepcopy(schema_dict) # Assert definitions assert_definitions_key(schema_dict) # Iterate over all definitions and remove the 'Auto-generated' class implementation for schema_def_name, schema_def_dict in schema_dict.get("definitions", {}).items(): if "description" not in schema_def_dict: continue schema_dict["definitions"][schema_def_name]["description"] = ( schema_def_dict.get("description", "").split("\n\n", 1)[-1] ) # Update top level description schema_dict["description"] = schema_dict.get("description", "").split("\n\n", 1)[-1] return schema_dict def fix_additional_properties(schema_dict: Dict, top_definition: str, sub_definition_keys: List) -> Dict: """ Fix the additionalProperties issues demonstrated in https://stoic-agnesi-d0ac4a.netlify.app/37 :param schema_dict: :return: """ # Always copy the input schema_dict = deepcopy(schema_dict) # Part 1, drop additionalProperties: false from Workflow, CommandLineTool and ExpressionTool definitions for definition_key in sub_definition_keys: _ = schema_dict["definitions"][definition_key].pop("additionalProperties", None) # Part 2 # For CWLFileorGraph definition, add in the collective set of properties keys defined under # Workflow, CommandLineTool, ExpressionTool, $graph and CWLMetadata # And for each property key set the value to true - property_keys = [] for definition_key in sub_definition_keys: if "properties" not in schema_dict["definitions"][definition_key]: continue property_keys.append(list(schema_dict["definitions"][definition_key]["properties"].keys())) property_keys = list(set(chain(*property_keys))) schema_dict["definitions"][top_definition]["properties"] = dict( map( lambda property_key_iter: (property_key_iter, True), property_keys ) ) # Part 2a, copy over patternProperties pattern_property_objects = {} for definition_key in sub_definition_keys: if "patternProperties" not in schema_dict["definitions"][definition_key]: continue pattern_property_objects.update( schema_dict["definitions"][definition_key]["patternProperties"] ) schema_dict["definitions"][top_definition]["patternProperties"] = pattern_property_objects # Make additionalProperties false to this top CWLDocumentMetadata schema_dict["definitions"][top_definition]["additionalProperties"] = False return schema_dict def fix_hints(schema_dict, definition_key): """ Hints property should be the same as requirements for the given key :param schema_dict: :param definition_key: :return: """ # Always do a deepcopy on the input schema_dict = deepcopy(schema_dict) # Assert definitions key assert_definitions_key(schema_dict) # Confirm definitions key exists if definition_key not in schema_dict["definitions"]: raise ValueError(f"Schema does not contain an '{definition_key}' key in 'definitions'") # Confirm that the definition_key has a properties key and the properties key is a dictionary if ( "properties" not in schema_dict["definitions"][definition_key] or not isinstance(schema_dict["definitions"][definition_key]["properties"], Dict) ): raise ValueError( f"Schema does not contain a 'properties' key in '{definition_key}.definitions' " "or 'properties' is not a dictionary" ) # Confirm that properties has a requirements key if "requirements" not in schema_dict["definitions"][definition_key]["properties"]: raise ValueError(f"Schema does not contain an 'requirements' key in '{definition_key}.properties'") # Copy requirements to hints schema_dict["definitions"][definition_key]["properties"]["hints"] = \ schema_dict["definitions"][definition_key]["properties"]["requirements"] return schema_dict def add_file_and_directory_to_schema(schema_dict: Dict) -> Dict: """ Add file and directory defintions to schema :param schema_dict: :return: """ # Always do a deepcopy on the input schema_dict = deepcopy(schema_dict) # Assert definitions key assert_definitions_key(schema_dict) # Add in the File and Directory definitions to the schema schema_dict['definitions'].update( CLEANED_FILE_DEFINITION ) schema_dict['definitions'].update( CLEANED_DIRECTORY_DEFINITION ) schema_dict['definitions'].update( CLEANED_ANY_DEFINITION ) return schema_dict def drop_properties_and_required(schema_dict: Dict) -> Dict: """ Drop the properties and required keys :param schema_dict: :return: """ # Always do a deepcopy on the input schema_dict = deepcopy(schema_dict) # Doesn't matter if they're not present _ = schema_dict.pop("properties", None) _ = schema_dict.pop("required", None) # Also drop additionalProperties _ = schema_dict.pop("additionalProperties", None) return schema_dict def main(): # Step 1 - read in existing schema schema_dict = read_schema_in_from_file(Path(sys.argv[1])) # Remove loading options from schema schema_dict = remove_loading_options_and_extension_fields_from_schema(schema_dict) # Rename all keys with trailing underscore schema_dict = rename_all_keys_with_trailing_underscore(schema_dict) # Drop the following definitions # DefaultFetcher # Dictionary # Dictionary # Fetcher # T for definition in DEFINTIIONS_TO_REMOVE: _ = schema_dict["definitions"].pop(definition) # Add the following definitions # File, Directory, schema_dict = add_file_and_directory_to_schema(schema_dict) # Drop existing properties and required list (this will be populated by the script) schema_dict = drop_properties_and_required(schema_dict) # Write out the new schema write_schema_out_to_file(schema_dict, Path(sys.argv[2])) if __name__ == "__main__": main() ```
Run the python script above ``` python3 refine_workflow_input_json_schema_template.py \ workflow_input_json_schema_template.primary.json \ workflow_input_json_schema_template.json ``` ## Part 5 - Run schema generation against all tests in the cwl v1.2 directory > Note there is a set of six urls and inputs that we test the schema generation against in the tests directory
Click to expand! ```python #!/usr/bin/env python3 import json from json import JSONDecodeError from pathlib import Path from subprocess import run from tempfile import TemporaryDirectory from jsonschema import validate from jsonschema.exceptions import SchemaError, ValidationError from ruamel.yaml import YAML from cwl_utils.loghandler import _logger as _cwlutilslogger FAILED_TESTS = [ "filesarray_secondaryfiles2", # Conditional logic too complex for json schema "wf_step_access_undeclared_param", # Inputs are valid, workflow expected to fail at tool level "input_records_file_entry_with_format_and_bad_regular_input_file_format", # Don't validate formats "secondary_files_missing", # Inputs are valid, workflow expected to fail at tool level "input_records_file_entry_with_format_and_bad_entry_file_format", # Don't validate formats "input_records_file_entry_with_format_and_bad_entry_array_file_format", # Don't validate formats "timelimit_basic", # Inputs are valid, workflow expected to fail at tool level "timelimit_invalid", # Inputs are valid, workflow expected to fail at tool level "timelimit_from_expression", # Inputs are valid, workflow expected to fail at tool level "timelimit_basic_wf", # Inputs are valid, workflow expected to fail at tool level "timelimit_from_expression_wf", # Inputs are valid, workflow expected to fail at tool level "networkaccess_disabled", # Inputs are valid, workflow expected to fail at tool level "glob_outside_outputs_fails", # Inputs are valid, workflow expected to fail at tool level "illegal_symlink", # Inputs are valid, workflow expected to fail at tool level "params_broken_null", # Inputs are valid, workflow expected to fail at tool level "length_for_non_array", # Inputs are valid, workflow expected to fail at tool level "capture_files", # Inputs are valid, workflow expected to fail at tool level "capture_dirs", # Inputs are valid, workflow expected to fail at tool level ] # Clone cwl1.2 repo into temp dir with TemporaryDirectory() as temp_dir: run(['git', 'clone', 'https://github.com/common-workflow-language/cwl-v1.2'], cwd=temp_dir) tests_dir = Path(temp_dir) / 'cwl-v1.2' / 'tests' # Open conformance test yaml file yaml = YAML() with open(Path(temp_dir) / 'cwl-v1.2' / "conformance_tests.yaml") as tests_yaml_h: tests_list = yaml.load(tests_yaml_h) failed_runs = [] for test_item in tests_list: id_ = test_item.get('id') # Check tool key exists if test_item.get('tool', None) is None: _cwlutilslogger.info(f"Skipping conformance test {id_}, no tool key") continue tool = Path(test_item.get('tool').split("#", 1)[0]) should_fail = test_item.get('should_fail', False) if "#" in test_item.get("tool") and not "#main" in test_item.get("tool"): _cwlutilslogger.info(f"Skipping conformance test {id_}, we cannot load non main graphs") continue if id_ in FAILED_TESTS: _cwlutilslogger.info(f"Skipping conformance test {id_}") continue _cwlutilslogger.info(f"Running conformance test {id_}") _cwlutilslogger.info(f"Generating schema for {tool.name}") schema_gen_proc = run( [ "python3", str(Path(__file__).parent / "cwl_utils" / "inputs_schema_gen.py"), Path(temp_dir) / 'cwl-v1.2' / tool ], capture_output=True ) if not schema_gen_proc.returncode == 0: _cwlutilslogger.error(schema_gen_proc.stderr.decode()) raise ChildProcessError schema_gen_stdout = schema_gen_proc.stdout.decode() if test_item.get('job', None) is None: continue job = Path(test_item.get('job')) try: input_schema_dict = json.loads(schema_gen_stdout) except JSONDecodeError: raise JSONDecodeError # Collect job with open(Path(temp_dir) / 'cwl-v1.2' / job) as job_h: job_dict = yaml.load(job_h) _cwlutilslogger.info(f"Testing {job.name} against schema generated for input {tool.name}") try: validate(job_dict, input_schema_dict) except (ValidationError, SchemaError) as err: if not should_fail: _cwlutilslogger.error(f"Failed schema validation with {err}") failed_runs.append(id_) else: if should_fail: _cwlutilslogger.error(f"Expected to fail but passed") failed_runs.append(id_) if len(failed_runs) > 0: _cwlutilslogger.error("The following tests failed") for failed_run in failed_runs: _cwlutilslogger.error(failed_run) ```
cwl_utils-0.41/cwl_utils/templates/workflow_input_json_schema_template.json0000644000000000000000000011254413615410400024625 0ustar00{ "$schema": "http://json-schema.org/draft-07/schema#", "definitions": { "InputArraySchema": { "additionalProperties": false, "description": "Auto-generated class implementation for https://w3id.org/cwl/cwl#InputArraySchema", "properties": { "doc": { "anyOf": [ { "items": { "type": "string" }, "type": "array" }, { "type": "string" } ], "description": "A documentation string for this object, or an array of strings which should be concatenated." }, "items": { "anyOf": [ { "$ref": "#/definitions/InputRecordSchema" }, { "$ref": "#/definitions/InputEnumSchema" }, { "$ref": "#/definitions/InputArraySchema" }, { "items": { "anyOf": [ { "$ref": "#/definitions/InputRecordSchema" }, { "$ref": "#/definitions/InputEnumSchema" }, { "$ref": "#/definitions/InputArraySchema" }, { "type": "string" } ] }, "type": "array" }, { "type": "string" } ], "description": "Defines the type of the array elements." }, "label": { "description": "A short, human-readable label of this object.", "type": "string" }, "name": { "description": "The identifier for this type", "type": "string" }, "type": { "const": "array", "description": "Must be `array`", "type": "string" } }, "required": [ "items", "type" ], "type": "object" }, "InputBinding": { "additionalProperties": false, "description": "Auto-generated class implementation for https://w3id.org/cwl/cwl#InputBinding", "properties": { "loadContents": { "description": "Use of `loadContents` in `InputBinding` is deprecated.\nPreserved for v1.0 backwards compatibility. Will be removed in\nCWL v2.0. Use `InputParameter.loadContents` instead.", "type": "boolean" } }, "required": [], "type": "object" }, "InputEnumSchema": { "additionalProperties": false, "description": "Auto-generated class implementation for https://w3id.org/cwl/cwl#InputEnumSchema", "properties": { "doc": { "anyOf": [ { "items": { "type": "string" }, "type": "array" }, { "type": "string" } ], "description": "A documentation string for this object, or an array of strings which should be concatenated." }, "label": { "description": "A short, human-readable label of this object.", "type": "string" }, "name": { "description": "The identifier for this type", "type": "string" }, "symbols": { "description": "Defines the set of valid symbols.", "items": { "type": "string" }, "type": "array" }, "type": { "const": "enum", "description": "Must be `enum`", "type": "string" } }, "required": [ "symbols", "type" ], "type": "object" }, "InputRecordField": { "additionalProperties": false, "description": "Auto-generated class implementation for https://w3id.org/cwl/cwl#InputRecordField", "properties": { "doc": { "anyOf": [ { "items": { "type": "string" }, "type": "array" }, { "type": "string" } ], "description": "A documentation string for this object, or an array of strings which should be concatenated." }, "format": { "anyOf": [ { "items": { "type": "string" }, "type": "array" }, { "type": "string" } ], "description": "Only valid when `type: File` or is an array of `items: File`.\n\nThis must be one or more IRIs of concept nodes\nthat represents file formats which are allowed as input to this\nparameter, preferably defined within an ontology. If no ontology is\navailable, file formats may be tested by exact match." }, "label": { "description": "A short, human-readable label of this object.", "type": "string" }, "loadContents": { "description": "Only valid when `type: File` or is an array of `items: File`.\n\nIf true, the file (or each file in the array) must be a UTF-8\ntext file 64 KiB or smaller, and the implementation must read\nthe entire contents of the file (or file array) and place it\nin the `contents` field of the File object for use by\nexpressions. If the size of the file is greater than 64 KiB,\nthe implementation must raise a fatal error.", "type": "boolean" }, "loadListing": { "description": "Only valid when `type: Directory` or is an array of `items: Directory`.\n\nSpecify the desired behavior for loading the `listing` field of\na Directory object for use by expressions.\n\nThe order of precedence for loadListing is:\n\n 1. `loadListing` on an individual parameter\n 2. Inherited from `LoadListingRequirement`\n 3. By default: `no_listing`", "enum": [ "deep_listing", "no_listing", "shallow_listing" ], "type": "string" }, "name": { "description": "The name of the field", "type": "string" }, "secondaryFiles": { "anyOf": [ { "$ref": "#/definitions/SecondaryFileSchema" }, { "items": { "$ref": "#/definitions/SecondaryFileSchema" }, "type": "array" } ], "description": "Only valid when `type: File` or is an array of `items: File`.\n\nProvides a pattern or expression specifying files or\ndirectories that should be included alongside the primary\nfile. Secondary files may be required or optional. When not\nexplicitly specified, secondary files specified for `inputs`\nare required and `outputs` are optional. An implementation\nmust include matching Files and Directories in the\n`secondaryFiles` property of the primary file. These Files\nand Directories must be transferred and staged alongside the\nprimary file. An implementation may fail workflow execution\nif a required secondary file does not exist.\n\nIf the value is an expression, the value of `self` in the expression\nmust be the primary input or output File object to which this binding\napplies. The `basename`, `nameroot` and `nameext` fields must be\npresent in `self`. For `CommandLineTool` outputs the `path` field must\nalso be present. The expression must return a filename string relative\nto the path to the primary File, a File or Directory object with either\n`path` or `location` and `basename` fields set, or an array consisting\nof strings or File or Directory objects. It is legal to reference an\nunchanged File or Directory object taken from input as a secondaryFile.\nThe expression may return \"null\" in which case there is no secondaryFile\nfrom that expression.\n\nTo work on non-filename-preserving storage systems, portable tool\ndescriptions should avoid constructing new values from `location`, but\nshould construct relative references using `basename` or `nameroot`\ninstead.\n\nIf a value in `secondaryFiles` is a string that is not an expression,\nit specifies that the following pattern should be applied to the path\nof the primary file to yield a filename relative to the primary File:\n\n 1. If string ends with `?` character, remove the last `?` and mark\n the resulting secondary file as optional.\n 2. If string begins with one or more caret `^` characters, for each\n caret, remove the last file extension from the path (the last\n period `.` and all following characters). If there are no file\n extensions, the path is unchanged.\n 3. Append the remainder of the string to the end of the file path." }, "streamable": { "description": "Only valid when `type: File` or is an array of `items: File`.\n\nA value of `true` indicates that the file is read or written\nsequentially without seeking. An implementation may use this flag to\nindicate whether it is valid to stream file contents using a named\npipe. Default: `false`.", "type": "boolean" }, "type": { "anyOf": [ { "$ref": "#/definitions/InputRecordSchema" }, { "$ref": "#/definitions/InputEnumSchema" }, { "$ref": "#/definitions/InputArraySchema" }, { "items": { "anyOf": [ { "$ref": "#/definitions/InputRecordSchema" }, { "$ref": "#/definitions/InputEnumSchema" }, { "$ref": "#/definitions/InputArraySchema" }, { "type": "string" } ] }, "type": "array" }, { "type": "string" } ], "description": "The field type" } }, "required": [ "name", "type" ], "type": "object" }, "InputRecordSchema": { "additionalProperties": false, "description": "Auto-generated class implementation for https://w3id.org/cwl/cwl#InputRecordSchema", "properties": { "doc": { "anyOf": [ { "items": { "type": "string" }, "type": "array" }, { "type": "string" } ], "description": "A documentation string for this object, or an array of strings which should be concatenated." }, "fields": { "description": "Defines the fields of the record.", "items": { "$ref": "#/definitions/InputRecordField" }, "type": "array" }, "label": { "description": "A short, human-readable label of this object.", "type": "string" }, "name": { "description": "The identifier for this type", "type": "string" }, "type": { "const": "record", "description": "Must be `record`", "type": "string" } }, "required": [ "type" ], "type": "object" }, "SecondaryFileSchema": { "additionalProperties": false, "description": "Auto-generated class implementation for https://w3id.org/cwl/cwl#SecondaryFileSchema\n\nSecondary files are specified using the following micro-DSL for secondary files:\n\n* If the value is a string, it is transformed to an object with two fields\n `pattern` and `required`\n* By default, the value of `required` is `null`\n (this indicates default behavior, which may be based on the context)\n* If the value ends with a question mark `?` the question mark is\n stripped off and the value of the field `required` is set to `False`\n* The remaining value is assigned to the field `pattern`\n\nFor implementation details and examples, please see\n[this section](SchemaSalad.html#Domain_Specific_Language_for_secondary_files)\nin the Schema Salad specification.", "properties": { "pattern": { "description": "Provides a pattern or expression specifying files or directories that\nshould be included alongside the primary file.\n\nIf the value is an expression, the value of `self` in the\nexpression must be the primary input or output File object to\nwhich this binding applies. The `basename`, `nameroot` and\n`nameext` fields must be present in `self`. For\n`CommandLineTool` inputs the `location` field must also be\npresent. For `CommandLineTool` outputs the `path` field must\nalso be present. If secondary files were included on an input\nFile object as part of the Process invocation, they must also\nbe present in `secondaryFiles` on `self`.\n\nThe expression must return either: a filename string relative\nto the path to the primary File, a File or Directory object\n(`class: File` or `class: Directory`) with either `location`\n(for inputs) or `path` (for outputs) and `basename` fields\nset, or an array consisting of strings or File or Directory\nobjects as previously described.\n\nIt is legal to use `location` from a File or Directory object\npassed in as input, including `location` from secondary files\non `self`. If an expression returns a File object with the\nsame `location` but a different `basename` as a secondary file\nthat was passed in, the expression result takes precedence.\nSetting the basename with an expression this way affects the\n`path` where the secondary file will be staged to in the\nCommandLineTool.\n\nThe expression may return \"null\" in which case there is no\nsecondary file from that expression.\n\nTo work on non-filename-preserving storage systems, portable\ntool descriptions should treat `location` as an\n[opaque identifier](#opaque-strings) and avoid constructing new\nvalues from `location`, but should construct relative references\nusing `basename` or `nameroot` instead, or propagate `location`\nfrom defined inputs.\n\nIf a value in `secondaryFiles` is a string that is not an expression,\nit specifies that the following pattern should be applied to the path\nof the primary file to yield a filename relative to the primary File:\n\n 1. If string ends with `?` character, remove the last `?` and mark\n the resulting secondary file as optional.\n 2. If string begins with one or more caret `^` characters, for each\n caret, remove the last file extension from the path (the last\n period `.` and all following characters). If there are no file\n extensions, the path is unchanged.\n 3. Append the remainder of the string to the end of the file path.", "type": "string" }, "required": { "description": "An implementation must not fail workflow execution if `required` is\nset to `false` and the expected secondary file does not exist.\nDefault value for `required` field is `true` for secondary files on\ninput and `false` for secondary files on output.", "type": [ "string", "boolean" ] } }, "required": [ "pattern" ], "type": "object" }, "File": { "additionalProperties": false, "description": "Represents a file (or group of files when `secondaryFiles` is provided) that\nwill be accessible by tools using standard POSIX file system call API such as\nopen(2) and read(2).\n\nFiles are represented as objects with `class` of `File`. File objects have\na number of properties that provide metadata about the file.\n\nThe `location` property of a File is a URI that uniquely identifies the\nfile. Implementations must support the `file://` URI scheme and may support\nother schemes such as `http://` and `https://`. The value of `location` may also be a\nrelative reference, in which case it must be resolved relative to the URI\nof the document it appears in. Alternately to `location`, implementations\nmust also accept the `path` property on File, which must be a filesystem\npath available on the same host as the CWL runner (for inputs) or the\nruntime environment of a command line tool execution (for command line tool\noutputs).\n\nIf no `location` or `path` is specified, a file object must specify\n`contents` with the UTF-8 text content of the file. This is a \"file\nliteral\". File literals do not correspond to external resources, but are\ncreated on disk with `contents` with when needed for executing a tool.\nWhere appropriate, expressions can return file literals to define new files\non a runtime. The maximum size of `contents` is 64 kilobytes.\n\nThe `basename` property defines the filename on disk where the file is\nstaged. This may differ from the resource name. If not provided,\n`basename` must be computed from the last path part of `location` and made\navailable to expressions.\n\nThe `secondaryFiles` property is a list of File or Directory objects that\nmust be staged in the same directory as the primary file. It is an error\nfor file names to be duplicated in `secondaryFiles`.\n\nThe `size` property is the size in bytes of the File. It must be computed\nfrom the resource and made available to expressions. The `checksum` field\ncontains a cryptographic hash of the file content for use it verifying file\ncontents. Implementations may, at user option, enable or disable\ncomputation of the `checksum` field for performance or other reasons.\nHowever, the ability to compute output checksums is required to pass the\nCWL conformance test suite.\n\nWhen executing a CommandLineTool, the files and secondary files may be\nstaged to an arbitrary directory, but must use the value of `basename` for\nthe filename. The `path` property must be file path in the context of the\ntool execution runtime (local to the compute node, or within the executing\ncontainer). All computed properties should be available to expressions.\nFile literals also must be staged and `path` must be set.\n\nWhen collecting CommandLineTool outputs, `glob` matching returns file paths\n(with the `path` property) and the derived properties. This can all be\nmodified by `outputEval`. Alternately, if the file `cwl.output.json` is\npresent in the output, `outputBinding` is ignored.\n\nFile objects in the output must provide either a `location` URI or a `path`\nproperty in the context of the tool execution runtime (local to the compute\nnode, or within the executing container).\n\nWhen evaluating an ExpressionTool, file objects must be referenced via\n`location` (the expression tool does not have access to files on disk so\n`path` is meaningless) or as file literals. It is legal to return a file\nobject with an existing `location` but a different `basename`. The\n`loadContents` field of ExpressionTool inputs behaves the same as on\nCommandLineTool inputs, however it is not meaningful on the outputs.\n\nAn ExpressionTool may forward file references from input to output by using\nthe same value for `location`.", "properties": { "basename": { "description": "The base name of the file, that is, the name of the file without any\nleading directory path. The base name must not contain a slash `/`.\n\nIf not provided, the implementation must set this field based on the\n`location` field by taking the final path component after parsing\n`location` as an IRI. If `basename` is provided, it is not required to\nmatch the value from `location`.\n\nWhen this file is made available to a CommandLineTool, it must be named\nwith `basename`, i.e. the final component of the `path` field must match\n`basename`.", "type": "string" }, "checksum": { "description": "Optional hash code for validating file integrity. Currently, must be in the form\n\"sha1$ + hexadecimal string\" using the SHA-1 algorithm.", "type": "string" }, "class": { "const": "File", "description": "Must be `File` to indicate this object describes a file.", "type": "string" }, "contents": { "description": "File contents literal.\n\nIf neither `location` nor `path` is provided, `contents` must be\nnon-null. The implementation must assign a unique identifier for the\n`location` field. When the file is staged as input to CommandLineTool,\nthe value of `contents` must be written to a file.\n\nIf `contents` is set as a result of a Javascript expression,\nan `entry` in `InitialWorkDirRequirement`, or read in from\n`cwl.output.json`, there is no specified upper limit on the\nsize of `contents`. Implementations may have practical limits\non the size of `contents` based on memory and storage\navailable to the workflow runner or other factors.\n\nIf the `loadContents` field of an `InputParameter` or\n`OutputParameter` is true, and the input or output File object\n`location` is valid, the file must be a UTF-8 text file 64 KiB\nor smaller, and the implementation must read the entire\ncontents of the file and place it in the `contents` field. If\nthe size of the file is greater than 64 KiB, the\nimplementation must raise a fatal error.", "type": "string" }, "dirname": { "description": "The name of the directory containing file, that is, the path leading up\nto the final slash in the path such that `dirname + '/' + basename ==\npath`.\n\nThe implementation must set this field based on the value of `path`\nprior to evaluating parameter references or expressions in a\nCommandLineTool document. This field must not be used in any other\ncontext.", "type": "string" }, "format": { "description": "The format of the file: this must be an IRI of a concept node that\nrepresents the file format, preferably defined within an ontology.\nIf no ontology is available, file formats may be tested by exact match.\n\nReasoning about format compatibility must be done by checking that an\ninput file format is the same, `owl:equivalentClass` or\n`rdfs:subClassOf` the format required by the input parameter.\n`owl:equivalentClass` is transitive with `rdfs:subClassOf`, e.g. if\n` owl:equivalentClass ` and ` owl:subclassOf
` then infer\n` owl:subclassOf `.\n\nFile format ontologies may be provided in the \"$schemas\" metadata at the\nroot of the document. If no ontologies are specified in `$schemas`, the\nruntime may perform exact file format matches.", "type": "string" }, "location": { "description": "An IRI that identifies the file resource. This may be a relative\nreference, in which case it must be resolved using the base IRI of the\ndocument. The location may refer to a local or remote resource; the\nimplementation must use the IRI to retrieve file content. If an\nimplementation is unable to retrieve the file content stored at a\nremote resource (due to unsupported protocol, access denied, or other\nissue) it must signal an error.\n\nIf the `location` field is not provided, the `contents` field must be\nprovided. The implementation must assign a unique identifier for\nthe `location` field.\n\nIf the `path` field is provided but the `location` field is not, an\nimplementation may assign the value of the `path` field to `location`,\nthen follow the rules above.", "type": "string" }, "nameext": { "description": "The basename extension such that `nameroot + nameext == basename`, and\n`nameext` is empty or begins with a period and contains at most one\nperiod. Leading periods on the basename are ignored; a basename of\n`.cshrc` will have an empty `nameext`.\n\nThe implementation must set this field automatically based on the value\nof `basename` prior to evaluating parameter references or expressions.", "type": "string" }, "nameroot": { "description": "The basename root such that `nameroot + nameext == basename`, and\n`nameext` is empty or begins with a period and contains at most one\nperiod. For the purposes of path splitting leading periods on the\nbasename are ignored; a basename of `.cshrc` will have a nameroot of\n`.cshrc`.\n\nThe implementation must set this field automatically based on the value\nof `basename` prior to evaluating parameter references or expressions.", "type": "string" }, "path": { "description": "The local host path where the File is available when a CommandLineTool is\nexecuted. This field must be set by the implementation. The final\npath component must match the value of `basename`. This field\nmust not be used in any other context. The command line tool being\nexecuted must be able to access the file at `path` using the POSIX\n`open(2)` syscall.\n\nAs a special case, if the `path` field is provided but the `location`\nfield is not, an implementation may assign the value of the `path`\nfield to `location`, and remove the `path` field.\n\nIf the `path` contains [POSIX shell metacharacters](http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_02)\n(`|`,`&`, `;`, `<`, `>`, `(`,`)`, `$`,`` ` ``, `\\`, `\"`, `'`,\n``, ``, and ``) or characters\n[not allowed](http://www.iana.org/assignments/idna-tables-6.3.0/idna-tables-6.3.0.xhtml)\nfor [Internationalized Domain Names for Applications](https://tools.ietf.org/html/rfc6452)\nthen implementations may terminate the process with a\n`permanentFailure`.", "type": "string" }, "secondaryFiles": { "description": "A list of additional files or directories that are associated with the\nprimary file and must be transferred alongside the primary file.\nExamples include indexes of the primary file, or external references\nwhich must be included when loading primary document. A file object\nlisted in `secondaryFiles` may itself include `secondaryFiles` for\nwhich the same rules apply.", "items": { "anyOf": [ { "$ref": "#/definitions/File" }, { "$ref": "#/definitions/Directory" } ] }, "type": "array" }, "size": { "description": "Optional file size (in bytes)", "type": "number" } }, "required": [ "class" ], "type": "object" }, "Directory": { "additionalProperties": false, "description": "Represents a directory to present to a command line tool.\n\nDirectories are represented as objects with `class` of `Directory`. Directory objects have\na number of properties that provide metadata about the directory.\n\nThe `location` property of a Directory is a URI that uniquely identifies\nthe directory. Implementations must support the file:// URI scheme and may\nsupport other schemes such as http://. Alternately to `location`,\nimplementations must also accept the `path` property on Directory, which\nmust be a filesystem path available on the same host as the CWL runner (for\ninputs) or the runtime environment of a command line tool execution (for\ncommand line tool outputs).\n\nA Directory object may have a `listing` field. This is a list of File and\nDirectory objects that are contained in the Directory. For each entry in\n`listing`, the `basename` property defines the name of the File or\nSubdirectory when staged to disk. If `listing` is not provided, the\nimplementation must have some way of fetching the Directory listing at\nruntime based on the `location` field.\n\nIf a Directory does not have `location`, it is a Directory literal. A\nDirectory literal must provide `listing`. Directory literals must be\ncreated on disk at runtime as needed.\n\nThe resources in a Directory literal do not need to have any implied\nrelationship in their `location`. For example, a Directory listing may\ncontain two files located on different hosts. It is the responsibility of\nthe runtime to ensure that those files are staged to disk appropriately.\nSecondary files associated with files in `listing` must also be staged to\nthe same Directory.\n\nWhen executing a CommandLineTool, Directories must be recursively staged\nfirst and have local values of `path` assigned.\n\nDirectory objects in CommandLineTool output must provide either a\n`location` URI or a `path` property in the context of the tool execution\nruntime (local to the compute node, or within the executing container).\n\nAn ExpressionTool may forward file references from input to output by using\nthe same value for `location`.\n\nName conflicts (the same `basename` appearing multiple times in `listing`\nor in any entry in `secondaryFiles` in the listing) is a fatal error.", "properties": { "basename": { "description": "The base name of the directory, that is, the name of the file without any\nleading directory path. The base name must not contain a slash `/`.\n\nIf not provided, the implementation must set this field based on the\n`location` field by taking the final path component after parsing\n`location` as an IRI. If `basename` is provided, it is not required to\nmatch the value from `location`.\n\nWhen this file is made available to a CommandLineTool, it must be named\nwith `basename`, i.e. the final component of the `path` field must match\n`basename`.", "type": "string" }, "class": { "const": "Directory", "description": "Must be `Directory` to indicate this object describes a Directory.", "type": "string" }, "listing": { "description": "List of files or subdirectories contained in this directory. The name\nof each file or subdirectory is determined by the `basename` field of\neach `File` or `Directory` object. It is an error if a `File` shares a\n`basename` with any other entry in `listing`. If two or more\n`Directory` object share the same `basename`, this must be treated as\nequivalent to a single subdirectory with the listings recursively\nmerged.", "items": { "anyOf": [ { "$ref": "#/definitions/File" }, { "$ref": "#/definitions/Directory" } ] }, "type": "array" }, "location": { "description": "An IRI that identifies the directory resource. This may be a relative\nreference, in which case it must be resolved using the base IRI of the\ndocument. The location may refer to a local or remote resource. If\nthe `listing` field is not set, the implementation must use the\nlocation IRI to retrieve directory listing. If an implementation is\nunable to retrieve the directory listing stored at a remote resource (due to\nunsupported protocol, access denied, or other issue) it must signal an\nerror.\n\nIf the `location` field is not provided, the `listing` field must be\nprovided. The implementation must assign a unique identifier for\nthe `location` field.\n\nIf the `path` field is provided but the `location` field is not, an\nimplementation may assign the value of the `path` field to `location`,\nthen follow the rules above.", "type": "string" }, "path": { "description": "The local path where the Directory is made available prior to executing a\nCommandLineTool. This must be set by the implementation. This field\nmust not be used in any other context. The command line tool being\nexecuted must be able to access the directory at `path` using the POSIX\n`opendir(2)` syscall.\n\nIf the `path` contains [POSIX shell metacharacters](http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_02)\n(`|`,`&`, `;`, `<`, `>`, `(`,`)`, `$`,`` ` ``, `\\`, `\"`, `'`,\n``, ``, and ``) or characters\n[not allowed](http://www.iana.org/assignments/idna-tables-6.3.0/idna-tables-6.3.0.xhtml)\nfor [Internationalized Domain Names for Applications](https://tools.ietf.org/html/rfc6452)\nthen implementations may terminate the process with a\n`permanentFailure`.", "type": "string" } }, "required": [ "class" ], "type": "object" }, "Any": { "description": "A placeholder for any type of CWL object.", "anyOf": [ { "type": "boolean" }, { "type": "integer" }, { "type": "number" }, { "type": "string" }, { "type": "array" }, { "type": "object" }, { "$ref": "#/definitions/File" }, { "$ref": "#/definitions/Directory" } ], "properties": { "format": true, "size": true, "listing": true, "checksum": true, "nameroot": true, "contents": true, "location": true, "path": true, "dirname": true, "nameext": true, "secondaryFiles": true, "class": true, "basename": true } } }, "description": "Auto-generated class implementation for https://w3id.org/cwl/cwl#WorkflowInputParameter", "type": "object" }cwl_utils-0.41/cwl_utils/testdata/EDAM_subset.owl0000644000000000000000000013642113615410400017026 0ustar00 ]> EDAM_topic http://edamontology.org/topic_ "EDAM topics" EDAM_operation http://edamontology.org/operation_ "EDAM operations" 09:07:2015 3625 formats "EDAM data formats" EDAM An ontology of bioinformatics topics, operations, types of data including identifiers, and data formats identifiers "EDAM types of identifiers" data "EDAM types of data" relations "EDAM relations" edam "EDAM" EDAM editors: Jon Ison, Matus Kalas, and Herve Menager. Contributors: Inge Jonassen, Dan Bolser, Hamish McWilliam, Mahmut Uludag, James Malone, Rodrigo Lopez, Steve Pettifer, and Peter Rice. Contibutions from these projects: EMBRACE, ELIXIR, and BioMedBridges (EU); EMBOSS (BBSRC, UK); eSysbio, FUGE Bioinformatics Platform, and ELIXIR.NO/Norwegian Bioinformatics Platform (Research Council of Norway). See http://edamontology.org for documentation and licence. operations "EDAM operations" EDAM http://edamontology.org/ "EDAM relations and concept properties" application/rdf+xml EDAM_data http://edamontology.org/data_ "EDAM types of data" concept_properties "EDAM concept properties" Jon Ison Matúš KalaÅ¡ Jon Ison, Matus Kalas, Hervé Ménager EDAM_format http://edamontology.org/format_ "EDAM data formats" topics "EDAM topics" 1.11 Hervé Ménager EDAM is an ontology of well established, familiar concepts that are prevalent within bioinformatics, including types of data and data identifiers, data formats, operations and topics. EDAM is a simple ontology - essentially a set of terms with synonyms and definitions - organised into an intuitive hierarchy for convenient use by curators, software developers and end-users. EDAM is suitable for large-scale semantic annotations and categorization of diverse bioinformatics resources. EDAM is also suitable for diverse application including for example within workbenches and workflow-management systems, software distributions, and resource registries. Created in Version in which a concept was created. true concept_properties Documentation Specification 'Documentation' trailing modifier (qualifier, 'documentation') of 'xref' links of 'Format' concepts. When 'true', the link is pointing to a page with explanation, description, documentation, or specification of the given data format. true concept_properties Example 'Example' concept property ('example' metadat tag) lists examples of valid values of types of identifiers (accessions). Applicable to some other types of data, too. true concept_properties Obsolete since true concept_properties Version in which a concept was made obsolete. Regular expression 'Regular expression' concept property ('regex' metadata tag) specifies the allowed values of types of identifiers (accessions). Applicable to some other types of data, too. concept_properties true has format "http://purl.obolibrary.org/obo/OBI_0000298" Subject A can be any concept or entity outside of an ontology (or an ontology concept in a role of an entity being semantically annotated) that is (or is in a role of) 'Data', or an input, output, input or output argument of an 'Operation'. Object B can either be a concept that is a 'Format', or in unexpected cases an entity outside of an ontology that is a 'Format' or is in the role of a 'Format'. In EDAM, 'has_format' is not explicitly defined between EDAM concepts, only the inverse 'is_format_of'. false OBO_REL:is_a relations http://www.loa-cnr.it/ontologies/DOLCE-Lite.owl#has-quality" false false edam 'A has_format B' defines for the subject A, that it has the object B as its data format. false has function http://wsio.org/has_function false OBO_REL:is_a OBO_REL:bearer_of edam Subject A can be any concept or entity outside of an ontology (or an ontology concept in a role of an entity being semantically annotated). Object B can either be a concept that is (or is in a role of) a function, or an entity outside of an ontology that is (or is in a role of) a function specification. In the scope of EDAM, 'has_function' serves only for relating annotated entities outside of EDAM with 'Operation' concepts. false http://www.loa-cnr.it/ontologies/DOLCE-Lite.owl#has-quality" true 'A has_function B' defines for the subject A, that it has the object B as its function. "http://purl.obolibrary.org/obo/OBI_0000306" relations false true In very unusual cases. Is defined anywhere? Not in the 'unknown' version of RO. 'OBO_REL:bearer_of' is narrower in the sense that it only relates ontological categories (concepts) that are an 'independent_continuant' (snap:IndependentContinuant) with ontological categories that are a 'specifically_dependent_continuant' (snap:SpecificallyDependentContinuant), and broader in the sense that it relates with any borne objects not just functions of the subject. OBO_REL:bearer_of has identifier false false relations OBO_REL:is_a edam 'A has_identifier B' defines for the subject A, that it has the object B as its identifier. Subject A can be any concept or entity outside of an ontology (or an ontology concept in a role of an entity being semantically annotated). Object B can either be a concept that is an 'Identifier', or an entity outside of an ontology that is an 'Identifier' or is in the role of an 'Identifier'. In EDAM, 'has_identifier' is not explicitly defined between EDAM concepts, only the inverse 'is_identifier_of'. false false has input OBO_REL:has_participant "http://purl.obolibrary.org/obo/OBI_0000293" false http://wsio.org/has_input Subject A can either be concept that is or has an 'Operation' function, or an entity outside of an ontology (or an ontology concept in a role of an entity being semantically annotated) that has an 'Operation' function or is an 'Operation'. Object B can be any concept or entity. In EDAM, only 'has_input' is explicitly defined between EDAM concepts ('Operation' 'has_input' 'Data'). The inverse, 'is_input_of', is not explicitly defined. relations OBO_REL:is_a false 'A has_input B' defines for the subject A, that it has the object B as a necessary or actual input or input argument. false true edam OBO_REL:has_participant 'OBO_REL:has_participant' is narrower in the sense that it only relates ontological categories (concepts) that are a 'process' (span:Process) with ontological categories that are a 'continuant' (snap:Continuant), and broader in the sense that it relates with any participating objects not just inputs or input arguments of the subject. true In very unusual cases. has output http://wsio.org/has_output Subject A can either be concept that is or has an 'Operation' function, or an entity outside of an ontology (or an ontology concept in a role of an entity being semantically annotated) that has an 'Operation' function or is an 'Operation'. Object B can be any concept or entity. In EDAM, only 'has_output' is explicitly defined between EDAM concepts ('Operation' 'has_output' 'Data'). The inverse, 'is_output_of', is not explicitly defined. edam "http://purl.obolibrary.org/obo/OBI_0000299" OBO_REL:is_a relations OBO_REL:has_participant true 'A has_output B' defines for the subject A, that it has the object B as a necessary or actual output or output argument. false false false 'OBO_REL:has_participant' is narrower in the sense that it only relates ontological categories (concepts) that are a 'process' (span:Process) with ontological categories that are a 'continuant' (snap:Continuant), and broader in the sense that it relates with any participating objects not just outputs or output arguments of the subject. It is also not clear whether an output (result) actually participates in the process that generates it. OBO_REL:has_participant In very unusual cases. true has topic relations true Subject A can be any concept or entity outside of an ontology (or an ontology concept in a role of an entity being semantically annotated). Object B can either be a concept that is a 'Topic', or in unexpected cases an entity outside of an ontology that is a 'Topic' or is in the role of a 'Topic'. In EDAM, only 'has_topic' is explicitly defined between EDAM concepts ('Operation' or 'Data' 'has_topic' 'Topic'). The inverse, 'is_topic_of', is not explicitly defined. false 'A has_topic B' defines for the subject A, that it has the object B as its topic (A is in the scope of a topic B). edam OBO_REL:is_a http://annotation-ontology.googlecode.com/svn/trunk/annotation-core.owl#hasTopic false "http://purl.obolibrary.org/obo/IAO_0000136" false http://www.loa-cnr.it/ontologies/DOLCE-Lite.owl#has-quality "http://purl.obolibrary.org/obo/OBI_0000298" In very unusual cases. true is format of false OBO_REL:is_a false false false 'A is_format_of B' defines for the subject A, that it is a data format of the object B. edam relations Subject A can either be a concept that is a 'Format', or in unexpected cases an entity outside of an ontology (or an ontology concept in a role of an entity being semantically annotated) that is a 'Format' or is in the role of a 'Format'. Object B can be any concept or entity outside of an ontology that is (or is in a role of) 'Data', or an input, output, input or output argument of an 'Operation'. In EDAM, only 'is_format_of' is explicitly defined between EDAM concepts ('Format' 'is_format_of' 'Data'). The inverse, 'has_format', is not explicitly defined. OBO_REL:quality_of http://www.loa-cnr.it/ontologies/DOLCE-Lite.owl#inherent-in OBO_REL:quality_of Is defined anywhere? Not in the 'unknown' version of RO. 'OBO_REL:quality_of' might be seen narrower in the sense that it only relates subjects that are a 'quality' (snap:Quality) with objects that are an 'independent_continuant' (snap:IndependentContinuant), and is broader in the sense that it relates any qualities of the object. is function of Subject A can either be concept that is (or is in a role of) a function, or an entity outside of an ontology (or an ontology concept in a role of an entity being semantically annotated) that is (or is in a role of) a function specification. Object B can be any concept or entity. Within EDAM itself, 'is_function_of' is not used. OBO_REL:inheres_in true OBO_REL:is_a false 'A is_function_of B' defines for the subject A, that it is a function of the object B. OBO_REL:function_of edam http://wsio.org/is_function_of relations http://www.loa-cnr.it/ontologies/DOLCE-Lite.owl#inherent-in false false OBO_REL:inheres_in Is defined anywhere? Not in the 'unknown' version of RO. 'OBO_REL:inheres_in' is narrower in the sense that it only relates ontological categories (concepts) that are a 'specifically_dependent_continuant' (snap:SpecificallyDependentContinuant) with ontological categories that are an 'independent_continuant' (snap:IndependentContinuant), and broader in the sense that it relates any borne subjects not just functions. true In very unusual cases. OBO_REL:function_of Is defined anywhere? Not in the 'unknown' version of RO. 'OBO_REL:function_of' only relates subjects that are a 'function' (snap:Function) with objects that are an 'independent_continuant' (snap:IndependentContinuant), so for example no processes. It does not define explicitly that the subject is a function of the object. is identifier of false false edam false relations Subject A can either be a concept that is an 'Identifier', or an entity outside of an ontology (or an ontology concept in a role of an entity being semantically annotated) that is an 'Identifier' or is in the role of an 'Identifier'. Object B can be any concept or entity outside of an ontology. In EDAM, only 'is_identifier_of' is explicitly defined between EDAM concepts (only 'Identifier' 'is_identifier_of' 'Data'). The inverse, 'has_identifier', is not explicitly defined. 'A is_identifier_of B' defines for the subject A, that it is an identifier of the object B. OBO_REL:is_a false is input of false http://wsio.org/is_input_of relations true false OBO_REL:participates_in OBO_REL:is_a "http://purl.obolibrary.org/obo/OBI_0000295" edam Subject A can be any concept or entity outside of an ontology (or an ontology concept in a role of an entity being semantically annotated). Object B can either be a concept that is or has an 'Operation' function, or an entity outside of an ontology that has an 'Operation' function or is an 'Operation'. In EDAM, 'is_input_of' is not explicitly defined between EDAM concepts, only the inverse 'has_input'. false 'A is_input_of B' defines for the subject A, that it as a necessary or actual input or input argument of the object B. 'OBO_REL:participates_in' is narrower in the sense that it only relates ontological categories (concepts) that are a 'continuant' (snap:Continuant) with ontological categories that are a 'process' (span:Process), and broader in the sense that it relates any participating subjects not just inputs or input arguments. OBO_REL:participates_in In very unusual cases. true is output of OBO_REL:is_a false false Subject A can be any concept or entity outside of an ontology (or an ontology concept in a role of an entity being semantically annotated). Object B can either be a concept that is or has an 'Operation' function, or an entity outside of an ontology that has an 'Operation' function or is an 'Operation'. In EDAM, 'is_output_of' is not explicitly defined between EDAM concepts, only the inverse 'has_output'. edam false 'A is_output_of B' defines for the subject A, that it as a necessary or actual output or output argument of the object B. OBO_REL:participates_in http://wsio.org/is_output_of true relations "http://purl.obolibrary.org/obo/OBI_0000312" In very unusual cases. true OBO_REL:participates_in 'OBO_REL:participates_in' is narrower in the sense that it only relates ontological categories (concepts) that are a 'continuant' (snap:Continuant) with ontological categories that are a 'process' (span:Process), and broader in the sense that it relates any participating subjects not just outputs or output arguments. It is also not clear whether an output (result) actually participates in the process that generates it. is topic of 'A is_topic_of B' defines for the subject A, that it is a topic of the object B (a topic A is the scope of B). relations OBO_REL:quality_of false true false Subject A can either be a concept that is a 'Topic', or in unexpected cases an entity outside of an ontology (or an ontology concept in a role of an entity being semantically annotated) that is a 'Topic' or is in the role of a 'Topic'. Object B can be any concept or entity outside of an ontology. In EDAM, 'is_topic_of' is not explicitly defined between EDAM concepts, only the inverse 'has_topic'. http://www.loa-cnr.it/ontologies/DOLCE-Lite.owl#inherent-in false OBO_REL:is_a edam OBO_REL:quality_of Is defined anywhere? Not in the 'unknown' version of RO. 'OBO_REL:quality_of' might be seen narrower in the sense that it only relates subjects that are a 'quality' (snap:Quality) with objects that are an 'independent_continuant' (snap:IndependentContinuant), and is broader in the sense that it relates any qualities of the object. In very unusual cases. true Resource type beta12orEarlier beta12orEarlier A type of computational resource used in bioinformatics. true FASTA beta12orEarlier FASTA format FASTA sequence format FASTA format including NCBI-style IDs. FASTA-like (text) This concept may also be used for the many non-standard FASTA-like formats. http://filext.com/file-extension/FASTA beta12orEarlier A text format resembling FASTA format. Textual format http://filext.com/file-extension/TSV http://www.iana.org/assignments/media-types/text/plain Textual format. Data in text format can be compressed into binary format, or can be a value of an XML element or attribute. Markup formats are not considered textual (or more precisely, not plain-textual). txt http://filext.com/file-extension/TXT Plain text http://www.iana.org/assignments/media-types/media-types.xhtml#text beta12orEarlier Alignment format (text) Text format for molecular sequence alignment information. beta12orEarlier Obsolete concept (EDAM) 1.2 Needed for conversion to the OBO format. An obsolete concept (redefined in EDAM). true cwl_utils-0.41/cwl_utils/testdata/bwa-mem-job.json0000644000000000000000000000074513615410400017177 0ustar00{ "reference": { "class": "File", "location": "chr20.fa", "size": 123, "checksum": "sha1$hash" }, "reads": [ { "class": "File", "location": "example_human_Illumina.pe_1.fastq" }, { "class": "File", "location": "example_human_Illumina.pe_2.fastq" } ], "min_std_max_min": [ 1, 2, 3, 4 ], "minimum_seed_length": 3 } cwl_utils-0.41/cwl_utils/testdata/bwa-mem-tool.cwl0000755000000000000000000000174513615410400017222 0ustar00#!/usr/bin/env cwl-runner cwlVersion: v1.2 class: CommandLineTool hints: - class: ResourceRequirement coresMin: 2 - class: DockerRequirement dockerPull: docker.io/python:3-slim inputs: - id: reference type: File inputBinding: { position: 2 } - id: reads type: type: array items: File inputBinding: { position: 3 } - id: minimum_seed_length type: int inputBinding: { position: 1, prefix: -m } - id: min_std_max_min type: { type: array, items: int } inputBinding: position: 1 prefix: -I itemSeparator: "," - id: args.py type: File default: class: File location: args.py inputBinding: position: -1 outputs: - id: sam type: ["null", File] outputBinding: { glob: output.sam } - id: args type: type: array items: string baseCommand: python arguments: - bwa - mem - valueFrom: $(runtime.cores) position: 1 prefix: -t stdout: output.sam cwl_utils-0.41/cwl_utils/testdata/cond-single-source-wf-003.1.cwl0000755000000000000000000000053613615410400021470 0ustar00#!/usr/bin/env cwl-runner class: Workflow cwlVersion: v1.2 inputs: val: int steps: step1: in: in1: val a_new_var: val run: foo-array.cwl when: $(inputs.in1 < 1) out: [out1] outputs: out1: type: string outputSource: step1/out1 pickValue: first_non_null requirements: InlineJavascriptRequirement: {} cwl_utils-0.41/cwl_utils/testdata/cond-single-source-wf-004.1.cwl0000755000000000000000000000054113615410400021465 0ustar00#!/usr/bin/env cwl-runner class: Workflow cwlVersion: v1.2 inputs: val: int steps: step1: in: in1: val a_new_var: val run: foo-array.cwl when: $(inputs.in1 < 1) out: [out1] outputs: out1: type: string outputSource: step1/out1 pickValue: the_only_non_null requirements: InlineJavascriptRequirement: {} cwl_utils-0.41/cwl_utils/testdata/cond-single-source-wf-005.1.cwl0000755000000000000000000000053613615410400021472 0ustar00#!/usr/bin/env cwl-runner class: Workflow cwlVersion: v1.2 inputs: val: int steps: step1: in: in1: val a_new_var: val run: foo-array.cwl when: $(inputs.in1 < 1) out: [out1] outputs: out1: type: string[] outputSource: step1/out1 pickValue: all_non_null requirements: InlineJavascriptRequirement: {} cwl_utils-0.41/cwl_utils/testdata/cond-wf-003.1.cwl0000755000000000000000000000102213615410400016702 0ustar00#!/usr/bin/env cwl-runner class: Workflow cwlVersion: v1.2 inputs: val: int steps: step1: in: in1: val a_new_var: val run: foo.cwl when: $(inputs.in1 < 1) out: [out1] step2: in: in1: val a_new_var: val run: foo.cwl when: $(inputs.a_new_var > 2) out: [out1] outputs: out1: type: string outputSource: - step1/out1 - step2/out1 pickValue: first_non_null requirements: InlineJavascriptRequirement: {} MultipleInputFeatureRequirement: {} cwl_utils-0.41/cwl_utils/testdata/cond-wf-004.1.cwl0000755000000000000000000000102513615410400016706 0ustar00#!/usr/bin/env cwl-runner class: Workflow cwlVersion: v1.2 inputs: val: int steps: step1: in: in1: val a_new_var: val run: foo.cwl when: $(inputs.in1 < 1) out: [out1] step2: in: in1: val a_new_var: val run: foo.cwl when: $(inputs.a_new_var > 2) out: [out1] outputs: out1: type: string outputSource: - step1/out1 - step2/out1 pickValue: the_only_non_null requirements: InlineJavascriptRequirement: {} MultipleInputFeatureRequirement: {} cwl_utils-0.41/cwl_utils/testdata/cond-wf-005.1.cwl0000755000000000000000000000102213615410400016704 0ustar00#!/usr/bin/env cwl-runner class: Workflow cwlVersion: v1.2 inputs: val: int steps: step1: in: in1: val a_new_var: val run: foo.cwl when: $(inputs.in1 < 1) out: [out1] step2: in: in1: val a_new_var: val run: foo.cwl when: $(inputs.a_new_var > 2) out: [out1] outputs: out1: type: string[] outputSource: - step1/out1 - step2/out1 pickValue: all_non_null requirements: InlineJavascriptRequirement: {} MultipleInputFeatureRequirement: {} cwl_utils-0.41/cwl_utils/testdata/count-lines6-single-source-wf_v1_0.cwl0000755000000000000000000000056313615410400023261 0ustar00#!/usr/bin/env cwl-runner class: Workflow cwlVersion: v1.0 requirements: - class: ScatterFeatureRequirement inputs: file1: File[] outputs: count_output: type: int outputSource: step1/output steps: step1: run: wc3-tool_v1_0.cwl scatter: file1 in: file1: source: file1 linkMerge: merge_nested out: [output]cwl_utils-0.41/cwl_utils/testdata/count-lines6-single-source-wf_v1_1.cwl0000755000000000000000000000056213615410400023261 0ustar00#!/usr/bin/env cwl-runner class: Workflow cwlVersion: v1.1 requirements: - class: ScatterFeatureRequirement inputs: file1: File[] outputs: count_output: type: int outputSource: step1/output steps: step1: run: wc3-tool_v1_1.cwl scatter: file1 in: file1: source: file1 linkMerge: merge_nested out: [output]cwl_utils-0.41/cwl_utils/testdata/count-lines6-single-source-wf_v1_2.cwl0000755000000000000000000000056213615410400023262 0ustar00#!/usr/bin/env cwl-runner class: Workflow cwlVersion: v1.2 requirements: - class: ScatterFeatureRequirement inputs: file1: File[] outputs: count_output: type: int outputSource: step1/output steps: step1: run: wc3-tool_v1_2.cwl scatter: file1 in: file1: source: file1 linkMerge: merge_nested out: [output]cwl_utils-0.41/cwl_utils/testdata/count-lines6-wf_v1_0.cwl0000755000000000000000000000067013615410400020503 0ustar00#!/usr/bin/env cwl-runner class: Workflow cwlVersion: v1.0 requirements: - class: ScatterFeatureRequirement - class: MultipleInputFeatureRequirement inputs: file1: File[] file2: File[] outputs: count_output: type: int outputSource: step1/output steps: step1: run: wc3-tool_v1_0.cwl scatter: file1 in: file1: source: [file1, file2] linkMerge: merge_nested out: [output]cwl_utils-0.41/cwl_utils/testdata/count-lines6-wf_v1_1.cwl0000755000000000000000000000067013615410400020504 0ustar00#!/usr/bin/env cwl-runner class: Workflow cwlVersion: v1.1 requirements: - class: ScatterFeatureRequirement - class: MultipleInputFeatureRequirement inputs: file1: File[] file2: File[] outputs: count_output: type: int outputSource: step1/output steps: step1: run: wc3-tool_v1_1.cwl scatter: file1 in: file1: source: [file1, file2] linkMerge: merge_nested out: [output]cwl_utils-0.41/cwl_utils/testdata/count-lines6-wf_v1_2.cwl0000755000000000000000000000067013615410400020505 0ustar00#!/usr/bin/env cwl-runner class: Workflow cwlVersion: v1.2 requirements: - class: ScatterFeatureRequirement - class: MultipleInputFeatureRequirement inputs: file1: File[] file2: File[] outputs: count_output: type: int outputSource: step1/output steps: step1: run: wc3-tool_v1_2.cwl scatter: file1 in: file1: source: [file1, file2] linkMerge: merge_nested out: [output]cwl_utils-0.41/cwl_utils/testdata/count-lines7-single-source-wf_v1_0.cwl0000755000000000000000000000045613615410400023263 0ustar00#!/usr/bin/env cwl-runner class: Workflow cwlVersion: v1.0 inputs: file1: File[] outputs: count_output: type: int outputSource: step1/output steps: step1: run: wc3-tool_v1_0.cwl in: file1: source: file1 linkMerge: merge_flattened out: [output]cwl_utils-0.41/cwl_utils/testdata/count-lines7-single-source-wf_v1_1.cwl0000755000000000000000000000045613615410400023264 0ustar00#!/usr/bin/env cwl-runner class: Workflow cwlVersion: v1.1 inputs: file1: File[] outputs: count_output: type: int outputSource: step1/output steps: step1: run: wc3-tool_v1_1.cwl in: file1: source: file1 linkMerge: merge_flattened out: [output]cwl_utils-0.41/cwl_utils/testdata/count-lines7-single-source-wf_v1_2.cwl0000755000000000000000000000045613615410400023265 0ustar00#!/usr/bin/env cwl-runner class: Workflow cwlVersion: v1.2 inputs: file1: File[] outputs: count_output: type: int outputSource: step1/output steps: step1: run: wc3-tool_v1_2.cwl in: file1: source: file1 linkMerge: merge_flattened out: [output]cwl_utils-0.41/cwl_utils/testdata/count-lines7-wf_v1_0.cwl0000755000000000000000000000060313615410400020500 0ustar00#!/usr/bin/env cwl-runner class: Workflow cwlVersion: v1.0 requirements: - class: MultipleInputFeatureRequirement inputs: file1: File[] file2: File[] outputs: count_output: type: int outputSource: step1/output steps: step1: run: wc3-tool_v1_0.cwl in: file1: source: [file1, file2] linkMerge: merge_flattened out: [output]cwl_utils-0.41/cwl_utils/testdata/count-lines7-wf_v1_1.cwl0000755000000000000000000000060313615410400020501 0ustar00#!/usr/bin/env cwl-runner class: Workflow cwlVersion: v1.1 requirements: - class: MultipleInputFeatureRequirement inputs: file1: File[] file2: File[] outputs: count_output: type: int outputSource: step1/output steps: step1: run: wc3-tool_v1_1.cwl in: file1: source: [file1, file2] linkMerge: merge_flattened out: [output]cwl_utils-0.41/cwl_utils/testdata/count-lines7-wf_v1_2.cwl0000755000000000000000000000060313615410400020502 0ustar00#!/usr/bin/env cwl-runner class: Workflow cwlVersion: v1.2 requirements: - class: MultipleInputFeatureRequirement inputs: file1: File[] file2: File[] outputs: count_output: type: int outputSource: step1/output steps: step1: run: wc3-tool_v1_2.cwl in: file1: source: [file1, file2] linkMerge: merge_flattened out: [output]cwl_utils-0.41/cwl_utils/testdata/debian_image_id.cwl0000755000000000000000000000031513615410400017752 0ustar00#!/usr/bin/env cwl-runner cwlVersion: v1.0 class: CommandLineTool requirements: DockerRequirement: dockerImageId: 'debian:stable-slim.img' inputs: message: string outputs: [] baseCommand: echo cwl_utils-0.41/cwl_utils/testdata/dir-job.yml0000644000000000000000000000005513615410400016252 0ustar00indir: class: Directory location: testdircwl_utils-0.41/cwl_utils/testdata/dir.cwl0000755000000000000000000000060013615410400015465 0ustar00#!/usr/bin/env cwl-runner class: CommandLineTool cwlVersion: v1.2 requirements: - class: ShellCommandRequirement inputs: indir: Directory outputs: outlist: type: File outputBinding: glob: output.txt arguments: ["cd", "$(inputs.indir.path)", {shellQuote: false, valueFrom: "&&"}, "find", ".", {shellQuote: false, valueFrom: "|"}, "sort"] stdout: output.txt cwl_utils-0.41/cwl_utils/testdata/dir4-job.yml0000644000000000000000000000025513615410400016340 0ustar00inf: class: File location: hello.tar secondaryFiles: - class: File location: index.py - class: Directory basename: xtestdir location: testdircwl_utils-0.41/cwl_utils/testdata/dockstore-tool-md5sum.cwl0000755000000000000000000000263413615410400021100 0ustar00#!/usr/bin/env cwl-runner class: CommandLineTool id: Md5sum label: Simple md5sum tool cwlVersion: v1.0 $namespaces: dct: http://purl.org/dc/terms/ foaf: http://xmlns.com/foaf/0.1/ doc: | [![Docker Repository on Quay.io](https://quay.io/repository/briandoconnor/dockstore-tool-md5sum/status "Docker Repository on Quay.io")](https://quay.io/repository/briandoconnor/dockstore-tool-md5sum) [![Build Status](https://travis-ci.org/briandoconnor/dockstore-tool-md5sum.svg)](https://travis-ci.org/briandoconnor/dockstore-tool-md5sum) A very, very simple Docker container for the md5sum command. See the [README](https://github.com/briandoconnor/dockstore-tool-md5sum/blob/master/README.md) for more information. #dct:creator: # '@id': http://orcid.org/0000-0002-7681-6415 # foaf:name: Brian O'Connor # foaf:mbox: briandoconnor@gmail.com requirements: - class: InlineJavascriptRequirement hints: DockerRequirement: dockerPull: quay.io/mr_c/dockstore-tool-md5sum:1.0.4 ResourceRequirement: # The command really requires very little resources. coresMin: 1 ramMin: 1024 outdirMin: 512 inputs: input_file: type: File inputBinding: position: 1 doc: The file that will have its md5sum calculated. outputs: output_file: type: File outputBinding: glob: md5sum.txt doc: A text file that contains a single line that is the md5sum of the input file. baseCommand: my_md5sum cwl_utils-0.41/cwl_utils/testdata/dockstore-tool-md5sum_v11.cwl0000755000000000000000000000271213615410400021564 0ustar00#!/usr/bin/env cwl-runner class: CommandLineTool id: Md5sum label: Simple md5sum tool cwlVersion: v1.1 $namespaces: dct: http://purl.org/dc/terms/ foaf: http://xmlns.com/foaf/0.1/ doc: | [![Docker Repository on Quay.io](https://quay.io/repository/briandoconnor/dockstore-tool-md5sum/status "Docker Repository on Quay.io")](https://quay.io/repository/briandoconnor/dockstore-tool-md5sum) [![Build Status](https://travis-ci.org/briandoconnor/dockstore-tool-md5sum.svg)](https://travis-ci.org/briandoconnor/dockstore-tool-md5sum) A very, very simple Docker container for the md5sum command. See the [README](https://github.com/briandoconnor/dockstore-tool-md5sum/blob/master/README.md) for more information. #dct:creator: # '@id': http://orcid.org/0000-0002-7681-6415 # foaf:name: Brian O'Connor # foaf:mbox: briandoconnor@gmail.com requirements: - class: InlineJavascriptRequirement hints: DockerRequirement: dockerPull: quay.io/mr_c/dockstore-tool-md5sum:1.0.4 ResourceRequirement: # The command really requires very little resources. coresMin: 1 ramMin: 1024 outdirMin: 512 inputs: input_file: type: File inputBinding: position: 1 doc: The file that will have its md5sum calculated. outputs: output_file: type: File format: http://edamontology.org/data_3671 outputBinding: glob: md5sum.txt doc: A text file that contains a single line that is the md5sum of the input file. baseCommand: my_md5sum cwl_utils-0.41/cwl_utils/testdata/dockstore-tool-md5sum_v12.cwl0000755000000000000000000000271213615410400021565 0ustar00#!/usr/bin/env cwl-runner class: CommandLineTool id: Md5sum label: Simple md5sum tool cwlVersion: v1.2 $namespaces: dct: http://purl.org/dc/terms/ foaf: http://xmlns.com/foaf/0.1/ doc: | [![Docker Repository on Quay.io](https://quay.io/repository/briandoconnor/dockstore-tool-md5sum/status "Docker Repository on Quay.io")](https://quay.io/repository/briandoconnor/dockstore-tool-md5sum) [![Build Status](https://travis-ci.org/briandoconnor/dockstore-tool-md5sum.svg)](https://travis-ci.org/briandoconnor/dockstore-tool-md5sum) A very, very simple Docker container for the md5sum command. See the [README](https://github.com/briandoconnor/dockstore-tool-md5sum/blob/master/README.md) for more information. #dct:creator: # '@id': http://orcid.org/0000-0002-7681-6415 # foaf:name: Brian O'Connor # foaf:mbox: briandoconnor@gmail.com requirements: - class: InlineJavascriptRequirement hints: DockerRequirement: dockerPull: quay.io/mr_c/dockstore-tool-md5sum:1.0.4 ResourceRequirement: # The command really requires very little resources. coresMin: 1 ramMin: 1024 outdirMin: 512 inputs: input_file: type: File inputBinding: position: 1 doc: The file that will have its md5sum calculated. outputs: output_file: type: File format: http://edamontology.org/data_3671 outputBinding: glob: md5sum.txt doc: A text file that contains a single line that is the md5sum of the input file. baseCommand: my_md5sum cwl_utils-0.41/cwl_utils/testdata/echo-tool-packed.cwl0000755000000000000000000000122213615410400020026 0ustar00#!/usr/bin/env cwl-runner cwlVersion: v1.2 $graph: - class: CommandLineTool id: first inputs: in: type: Any outputs: out: type: string outputBinding: glob: out.txt loadContents: true outputEval: $(self[0].contents) baseCommand: [ echo, first ] stdout: out.txt - class: CommandLineTool id: main inputs: in: type: Any inputBinding: {} outputs: out: type: string outputBinding: glob: out.txt loadContents: true outputEval: $(self[0].contents) baseCommand: echo stdout: out.txt cwl_utils-0.41/cwl_utils/testdata/echo_v1_0.cwl0000755000000000000000000000032713615410400016460 0ustar00#!/usr/bin/env cwl-runner cwlVersion: v1.0 class: CommandLineTool baseCommand: echo inputs: echo_in: type: - string - string[] inputBinding: {} stdout: out.txt outputs: txt: type: stdout cwl_utils-0.41/cwl_utils/testdata/echo_v1_1.cwl0000755000000000000000000000032713615410400016461 0ustar00#!/usr/bin/env cwl-runner cwlVersion: v1.1 class: CommandLineTool baseCommand: echo inputs: echo_in: type: - string - string[] inputBinding: {} stdout: out.txt outputs: txt: type: stdout cwl_utils-0.41/cwl_utils/testdata/echo_v1_2.cwl0000755000000000000000000000032713615410400016462 0ustar00#!/usr/bin/env cwl-runner cwlVersion: v1.2 class: CommandLineTool baseCommand: echo inputs: echo_in: type: - string - string[] inputBinding: {} stdout: out.txt outputs: txt: type: stdout cwl_utils-0.41/cwl_utils/testdata/env-job.json0000644000000000000000000000003713615410400016434 0ustar00{ "in": "hello test env" } cwl_utils-0.41/cwl_utils/testdata/env-job3.yaml0000644000000000000000000000020513615410400016505 0ustar00in: "hello test env" cwl:requirements: - class: EnvVarRequirement envDef: - envName: TEST_ENV envValue: $(inputs.in) cwl_utils-0.41/cwl_utils/testdata/env-tool1.cwl0000755000000000000000000000044513615410400016542 0ustar00#!/usr/bin/env cwl-runner class: CommandLineTool cwlVersion: v1.2 inputs: in: string outputs: out: type: File outputBinding: glob: out requirements: EnvVarRequirement: envDef: TEST_ENV: $(inputs.in) baseCommand: ["/bin/sh", "-c", "echo $TEST_ENV"] stdout: out cwl_utils-0.41/cwl_utils/testdata/foo-array.cwl0000755000000000000000000000040113615410400016605 0ustar00#!/usr/bin/env cwl-runner class: CommandLineTool cwlVersion: v1.2 inputs: in1: int baseCommand: [echo] outputs: out1: type: string[] outputBinding: outputEval: ${ return [foo, inputs.in1]; } requirements: InlineJavascriptRequirement: {} cwl_utils-0.41/cwl_utils/testdata/foo.cwl0000755000000000000000000000030213615410400015471 0ustar00#!/usr/bin/env cwl-runner class: CommandLineTool cwlVersion: v1.2 inputs: in1: int baseCommand: [echo] outputs: out1: type: string outputBinding: outputEval: foo $(inputs.in1) cwl_utils-0.41/cwl_utils/testdata/formattest-job.json0000644000000000000000000000017013615410400020032 0ustar00{ "input": { "class": "File", "location": "whale.txt", "format": "edam:format_2330" } } cwl_utils-0.41/cwl_utils/testdata/formattest2.cwl0000755000000000000000000000076013615410400017170 0ustar00#!/usr/bin/env cwl-runner $namespaces: edam: http://edamontology.org/ $schemas: - EDAM_subset.owl class: CommandLineTool cwlVersion: v1.2 doc: "Reverse each line using the `rev` command" hints: DockerRequirement: dockerPull: docker.io/debian:stable-slim inputs: input: type: File inputBinding: {} format: edam:format_2330 outputs: output: type: File outputBinding: glob: output.txt format: $(inputs.input.format) baseCommand: rev stdout: output.txt cwl_utils-0.41/cwl_utils/testdata/formattest2_v1_0.cwl0000755000000000000000000000076013615410400020015 0ustar00#!/usr/bin/env cwl-runner $namespaces: edam: http://edamontology.org/ $schemas: - EDAM_subset.owl class: CommandLineTool cwlVersion: v1.0 doc: "Reverse each line using the `rev` command" hints: DockerRequirement: dockerPull: docker.io/debian:stable-slim inputs: input: type: File inputBinding: {} format: edam:format_2330 outputs: output: type: File outputBinding: glob: output.txt format: $(inputs.input.format) baseCommand: rev stdout: output.txt cwl_utils-0.41/cwl_utils/testdata/formattest2_v1_1.cwl0000755000000000000000000000076013615410400020016 0ustar00#!/usr/bin/env cwl-runner $namespaces: edam: http://edamontology.org/ $schemas: - EDAM_subset.owl class: CommandLineTool cwlVersion: v1.1 doc: "Reverse each line using the `rev` command" hints: DockerRequirement: dockerPull: docker.io/debian:stable-slim inputs: input: type: File inputBinding: {} format: edam:format_2330 outputs: output: type: File outputBinding: glob: output.txt format: $(inputs.input.format) baseCommand: rev stdout: output.txt cwl_utils-0.41/cwl_utils/testdata/gx_edam.ttl0000644000000000000000000000041513615410400016332 0ustar00@prefix gx: . @prefix owl: . @prefix rdfs: . @prefix edam: . gx:fasta a owl:Class . gx:fasta owl:equivalentClass edam:format_1929 . cwl_utils-0.41/cwl_utils/testdata/js-expr-req-wf.cwl0000755000000000000000000000116713615410400017507 0ustar00#!/usr/bin/env cwl-runner cwlVersion: v1.2 $graph: - id: tool class: CommandLineTool requirements: InlineJavascriptRequirement: expressionLib: - "function foo() { return 2; }" inputs: [] outputs: out: stdout arguments: [echo, $(foo())] stdout: whatever.txt - id: wf class: Workflow requirements: InlineJavascriptRequirement: expressionLib: - "function bar() { return 1; }" inputs: [] outputs: out: type: File outputSource: tool/out steps: tool: run: "#tool" in: {} out: [out] cwl_utils-0.41/cwl_utils/testdata/lib.js0000644000000000000000000000016613615410400015310 0ustar00var foo = function(x) { return 2 * x } var bar = function(n, x) { return n + " engineers walk into a " + x } cwl_utils-0.41/cwl_utils/testdata/map-ordering-v1_0.cwl0000755000000000000000000000133713615410400020046 0ustar00#!/usr/bin/env cwl-runner cwlVersion: v1.0 class: Workflow inputs: 09first_input: string 05second_input: int 01third_input: File steps: zz_step_one: run: class: ExpressionTool inputs: [] outputs: [] expression: ${return {}; } requirements: InlineJavascriptRequirement: {} in: [] out: [] 00_step_two: out: [] run: inputs: [] requirements: InlineJavascriptRequirement: {} outputs: [] expression: ${return {}; } class: ExpressionTool in: [] outputs: zz_first_output: type: File outputSource: 01third_input ll_second_output: type: string outputSource: 09first_input aa_third_output: type: int outputSource: 05second_input cwl_utils-0.41/cwl_utils/testdata/map-ordering-v1_1.cwl0000755000000000000000000000133713615410400020047 0ustar00#!/usr/bin/env cwl-runner cwlVersion: v1.1 class: Workflow inputs: 09first_input: string 05second_input: int 01third_input: File steps: zz_step_one: run: class: ExpressionTool inputs: [] outputs: [] expression: ${return {}; } requirements: InlineJavascriptRequirement: {} in: [] out: [] 00_step_two: out: [] run: inputs: [] requirements: InlineJavascriptRequirement: {} outputs: [] expression: ${return {}; } class: ExpressionTool in: [] outputs: zz_first_output: type: File outputSource: 01third_input ll_second_output: type: string outputSource: 09first_input aa_third_output: type: int outputSource: 05second_input cwl_utils-0.41/cwl_utils/testdata/map-ordering-v1_2.cwl0000755000000000000000000000133713615410400020050 0ustar00#!/usr/bin/env cwl-runner cwlVersion: v1.2 class: Workflow inputs: 09first_input: string 05second_input: int 01third_input: File steps: zz_step_one: run: class: ExpressionTool inputs: [] outputs: [] expression: ${return {}; } requirements: InlineJavascriptRequirement: {} in: [] out: [] 00_step_two: out: [] run: inputs: [] requirements: InlineJavascriptRequirement: {} outputs: [] expression: ${return {}; } class: ExpressionTool in: [] outputs: zz_first_output: type: File outputSource: 01third_input ll_second_output: type: string outputSource: 09first_input aa_third_output: type: int outputSource: 05second_input cwl_utils-0.41/cwl_utils/testdata/md5sum.cwl0000755000000000000000000000042613615410400016127 0ustar00#!/usr/bin/env cwl-runner cwlVersion: v1.0 class: Workflow inputs: input_file: File outputs: output_file: type: File outputSource: md5sum/output_file steps: md5sum: run: dockstore-tool-md5sum.cwl in: input_file: input_file out: [output_file] cwl_utils-0.41/cwl_utils/testdata/md5sum.input0000644000000000000000000000000613615410400016470 0ustar00hello cwl_utils-0.41/cwl_utils/testdata/md5sum.json0000644000000000000000000000017013615410400016304 0ustar00{"output_file": {"path": "/tmp/md5sum.txt", "class": "File"}, "input_file": {"path": "md5sum.input", "class": "File"}} cwl_utils-0.41/cwl_utils/testdata/md5sum_v11.cwl0000755000000000000000000000043213615410400016613 0ustar00#!/usr/bin/env cwl-runner cwlVersion: v1.1 class: Workflow inputs: input_file: File outputs: output_file: type: File outputSource: md5sum/output_file steps: md5sum: run: dockstore-tool-md5sum_v11.cwl in: input_file: input_file out: [output_file] cwl_utils-0.41/cwl_utils/testdata/md5sum_v12.cwl0000755000000000000000000000043213615410400016614 0ustar00#!/usr/bin/env cwl-runner cwlVersion: v1.2 class: Workflow inputs: input_file: File outputs: output_file: type: File outputSource: md5sum/output_file steps: md5sum: run: dockstore-tool-md5sum_v12.cwl in: input_file: input_file out: [output_file] cwl_utils-0.41/cwl_utils/testdata/nested-array-job.yml0000644000000000000000000000001613615410400020067 0ustar00letters: [[a]]cwl_utils-0.41/cwl_utils/testdata/record-output-wf_v1_0.cwl0000755000000000000000000000072313615410400020770 0ustar00#!/usr/bin/env cwl-runner class: Workflow cwlVersion: v1.0 inputs: irec: type: name: irec type: record fields: - name: ifoo type: File - name: ibar type: File outputs: orec: type: type: record fields: - name: ofoo type: File - name: obar type: File outputSource: step1/orec steps: step1: run: record-output_v1_0.cwl in: irec: irec out: [orec]cwl_utils-0.41/cwl_utils/testdata/record-output-wf_v1_1.cwl0000755000000000000000000000074413615410400020774 0ustar00#!/usr/bin/env cwl-runner class: Workflow cwlVersion: v1.1 inputs: irec: type: name: irec type: record fields: - name: ifoo type: File - name: ibar type: File outputs: orec: type: name: orec type: record fields: - name: ofoo type: File - name: obar type: File outputSource: step1/orec steps: step1: run: record-output_v1_1.cwl in: irec: irec out: [orec]cwl_utils-0.41/cwl_utils/testdata/record-output-wf_v1_2.cwl0000755000000000000000000000074413615410400020775 0ustar00#!/usr/bin/env cwl-runner class: Workflow cwlVersion: v1.2 inputs: irec: type: name: irec type: record fields: - name: ifoo type: File - name: ibar type: File outputs: orec: type: name: orec type: record fields: - name: ofoo type: File - name: obar type: File outputSource: step1/orec steps: step1: run: record-output_v1_2.cwl in: irec: irec out: [orec]cwl_utils-0.41/cwl_utils/testdata/record-output_v1_0.cwl0000755000000000000000000000157113615410400020360 0ustar00#!/usr/bin/env cwl-runner class: CommandLineTool cwlVersion: v1.0 hints: ResourceRequirement: ramMin: 8 requirements: - class: ShellCommandRequirement inputs: irec: type: name: irec type: record fields: - name: ifoo type: File inputBinding: position: 2 - name: ibar type: File inputBinding: position: 6 outputs: orec: type: name: orec type: record fields: - name: ofoo type: File outputBinding: glob: foo - name: obar type: File outputBinding: glob: bar arguments: - {valueFrom: "cat", position: 1} - {valueFrom: "> foo", position: 3, shellQuote: false} - {valueFrom: "&&", position: 4, shellQuote: false} - {valueFrom: "cat", position: 5} - {valueFrom: "> bar", position: 7, shellQuote: false} cwl_utils-0.41/cwl_utils/testdata/record-output_v1_1.cwl0000755000000000000000000000151513615410400020357 0ustar00#!/usr/bin/env cwl-runner class: CommandLineTool cwlVersion: v1.1 requirements: - class: ShellCommandRequirement inputs: irec: type: name: irec type: record fields: - name: ifoo type: File inputBinding: position: 2 - name: ibar type: File inputBinding: position: 6 outputs: orec: type: name: orec type: record fields: - name: ofoo type: File outputBinding: glob: foo - name: obar type: File outputBinding: glob: bar arguments: - {valueFrom: "cat", position: 1} - {valueFrom: "> foo", position: 3, shellQuote: false} - {valueFrom: "&&", position: 4, shellQuote: false} - {valueFrom: "cat", position: 5} - {valueFrom: "> bar", position: 7, shellQuote: false} cwl_utils-0.41/cwl_utils/testdata/record-output_v1_2.cwl0000755000000000000000000000151513615410400020360 0ustar00#!/usr/bin/env cwl-runner class: CommandLineTool cwlVersion: v1.2 requirements: - class: ShellCommandRequirement inputs: irec: type: name: irec type: record fields: - name: ifoo type: File inputBinding: position: 2 - name: ibar type: File inputBinding: position: 6 outputs: orec: type: name: orec type: record fields: - name: ofoo type: File outputBinding: glob: foo - name: obar type: File outputBinding: glob: bar arguments: - {valueFrom: "cat", position: 1} - {valueFrom: "> foo", position: 3, shellQuote: false} - {valueFrom: "&&", position: 4, shellQuote: false} - {valueFrom: "cat", position: 5} - {valueFrom: "> bar", position: 7, shellQuote: false} cwl_utils-0.41/cwl_utils/testdata/rename-inputs.cwl0000755000000000000000000000325013615410400017502 0ustar00#!/usr/bin/env cwl-runner id: InputSecondaryFileConformanceTest class: CommandLineTool cwlVersion: v1.2 doc: | Simple test to confirm the implementation of expressions returning a File within a CommandInputParameter.secondaryFile field. Use GREP to filter the result from ls to ensure we only get the secondary files in there. Related links: - Issue: https://github.com/common-workflow-language/cwltool/issues/1232 - PR: https://github.com/common-workflow-language/cwltool/pull/1233 - Discourse: https://cwl.discourse.group/t/ask-cwl-to-rename-a-secondary-file/72 inputs: - id: inputWithSecondary type: File doc: | This input will with a secondary file `.accessory`. You could create these files (and its accessory) with: ```bash touch secondary_file_test.txt touch secondary_file_test.txt.accessory ``` secondaryFiles: - | ${ function resolveSecondary(base, secPattern) { if (secPattern[0] == '^') { var spl = base.split('.'); var endIndex = spl.length > 1 ? spl.length - 1 : 1; return resolveSecondary(spl.slice(undefined, endIndex).join("."), secPattern.slice(1)); } return base + secPattern; } return [{ "class": "File", "location": inputs.accessory.location, "basename": resolveSecondary(self.basename, '^.accessory') }]; } - id: accessory type: File arguments: - "ls" - $(inputs.inputWithSecondary.dirname) - valueFrom: "|" shellQuote: false - "grep" - "secondary" outputs: - id: output_file type: stdout stdout: result requirements: InlineJavascriptRequirement: {} ShellCommandRequirement: {} cwl_utils-0.41/cwl_utils/testdata/rename-inputs.yml0000644000000000000000000000022513615410400017512 0ustar00inputWithSecondary: class: File location: secondary_file_test.txt accessory: class: File location: secondary_file_test.txt.accessory cwl_utils-0.41/cwl_utils/testdata/revsort-job.json0000644000000000000000000000010613615410400017345 0ustar00{ "input": { "class": "File", "location": "whale.txt" } } cwl_utils-0.41/cwl_utils/testdata/revsort-packed.cwl0000755000000000000000000000752313615410400017653 0ustar00#!/usr/bin/env cwl-runner { "cwlVersion": "v1.2", "$graph": [ { "class": "Workflow", "doc": "Reverse the lines in a document, then sort those lines.", "hints": [ { "class": "DockerRequirement", "dockerPull": "docker.io/debian:stable-slim" } ], "inputs": [ { "type": "File", "doc": "The input file to be processed.", "id": "#main/input" }, { "type": "boolean", "default": true, "doc": "If true, reverse (descending) sort", "id": "#main/reverse_sort" } ], "outputs": [ { "type": "File", "outputSource": "#main/sorted/output", "doc": "The output with the lines reversed and sorted.", "id": "#main/output" } ], "steps": [ { "in": [ { "source": "#main/input", "id": "#main/rev/input" } ], "out": [ "#main/rev/output" ], "run": "#revtool.cwl", "id": "#main/rev" }, { "in": [ { "source": "#main/rev/output", "id": "#main/sorted/input" }, { "source": "#main/reverse_sort", "id": "#main/sorted/reverse" } ], "out": [ "#main/sorted/output" ], "run": "#sorttool.cwl", "id": "#main/sorted" } ], "id": "#main" }, { "class": "CommandLineTool", "doc": "Reverse each line using the `rev` command", "inputs": [ { "type": "File", "inputBinding": {}, "id": "#revtool.cwl/input" } ], "outputs": [ { "type": "File", "outputBinding": { "glob": "output.txt" }, "id": "#revtool.cwl/output" } ], "baseCommand": "rev", "stdout": "output.txt", "id": "#revtool.cwl" }, { "class": "CommandLineTool", "doc": "Sort lines using the `sort` command", "inputs": [ { "id": "#sorttool.cwl/reverse", "type": "boolean", "inputBinding": { "position": 1, "prefix": "-r" } }, { "id": "#sorttool.cwl/input", "type": "File", "inputBinding": { "position": 2 } } ], "outputs": [ { "id": "#sorttool.cwl/output", "type": "File", "outputBinding": { "glob": "output.txt" } } ], "baseCommand": "sort", "stdout": "output.txt", "id": "#sorttool.cwl" } ] } cwl_utils-0.41/cwl_utils/testdata/revsort-run-1-packed.cwl0000755000000000000000000001053613615410400020611 0ustar00#!/usr/bin/env cwl-runner { "$graph": [ { "class": "Workflow", "doc": "Reverse the lines in a document, then sort those lines.", "hints": [ { "class": "DockerRequirement", "dockerPull": "debian:8" } ], "inputs": [ { "type": "File", "doc": "The input file to be processed.", "format": "https://www.iana.org/assignments/media-types/text/plain", "default": { "class": "File", "location": "file:///home/stain/src/cwltool/tests/wf/hello.txt" }, "id": "#main/input" }, { "type": "boolean", "default": true, "doc": "If true, reverse (decending) sort", "id": "#main/reverse_sort" } ], "outputs": [ { "type": "File", "outputSource": "#main/sorted/output", "doc": "The output with the lines reversed and sorted.", "id": "#main/output" } ], "steps": [ { "in": [ { "source": "#main/input", "id": "#main/rev/input" } ], "out": [ "#main/rev/output" ], "run": "#revtool.cwl", "id": "#main/rev" }, { "in": [ { "source": "#main/rev/output", "id": "#main/sorted/input" }, { "source": "#main/reverse_sort", "id": "#main/sorted/reverse" } ], "out": [ "#main/sorted/output" ], "run": "#sorttool.cwl", "id": "#main/sorted" } ], "id": "#main", "$namespaces": { "iana": "https://www.iana.org/assignments/media-types/" } }, { "class": "CommandLineTool", "doc": "Reverse each line using the `rev` command", "inputs": [ { "type": "File", "inputBinding": {}, "id": "#revtool.cwl/input" } ], "outputs": [ { "type": "File", "outputBinding": { "glob": "output.txt" }, "id": "#revtool.cwl/output" } ], "baseCommand": "rev", "stdout": "output.txt", "id": "#revtool.cwl" }, { "class": "CommandLineTool", "doc": "Sort lines using the `sort` command", "inputs": [ { "id": "#sorttool.cwl/reverse", "type": "boolean", "inputBinding": { "position": 1, "prefix": "--reverse" } }, { "id": "#sorttool.cwl/input", "type": "File", "inputBinding": { "position": 2 } } ], "outputs": [ { "id": "#sorttool.cwl/output", "type": "File", "outputBinding": { "glob": "output.txt" } } ], "baseCommand": "sort", "stdout": "output.txt", "id": "#sorttool.cwl" } ], "cwlVersion": "v1.0", "$schemas": [ "file:///home/stain/src/cwltool/tests/wf/empty.ttl", "file:///home/stain/src/cwltool/tests/wf/empty2.ttl" ] } cwl_utils-0.41/cwl_utils/testdata/scatter-wf1_v1_0.cwl0000755000000000000000000000123213615410400017676 0ustar00#!/usr/bin/env cwl-runner cwlVersion: v1.0 class: Workflow inputs: inp: string[] outputs: out: type: string[] outputSource: step1/echo_out requirements: - class: ScatterFeatureRequirement steps: step1: in: echo_in: inp out: [echo_out] scatter: echo_in run: class: CommandLineTool inputs: echo_in: type: string inputBinding: {} outputs: echo_out: type: string outputBinding: glob: "step1_out" loadContents: true outputEval: $(self[0].contents) baseCommand: "echo" arguments: - "-n" - "foo"cwl_utils-0.41/cwl_utils/testdata/scatter-wf1_v1_1.cwl0000755000000000000000000000126413615410400017704 0ustar00#!/usr/bin/env cwl-runner cwlVersion: v1.1 class: Workflow inputs: inp: string[] outputs: out: type: string[] outputSource: step1/echo_out requirements: - class: ScatterFeatureRequirement steps: step1: in: echo_in: inp out: [echo_out] scatter: echo_in run: class: CommandLineTool inputs: echo_in: type: string inputBinding: {} outputs: echo_out: type: string outputBinding: glob: "step1_out" loadContents: true outputEval: $(self[0].contents) baseCommand: "echo" arguments: - "-n" - "foo" stdout: "step1_out"cwl_utils-0.41/cwl_utils/testdata/scatter-wf1_v1_2.cwl0000755000000000000000000000126413615410400017705 0ustar00#!/usr/bin/env cwl-runner cwlVersion: v1.2 class: Workflow inputs: inp: string[] outputs: out: type: string[] outputSource: step1/echo_out requirements: - class: ScatterFeatureRequirement steps: step1: in: echo_in: inp out: [echo_out] scatter: echo_in run: class: CommandLineTool inputs: echo_in: type: string inputBinding: {} outputs: echo_out: type: string outputBinding: glob: "step1_out" loadContents: true outputEval: $(self[0].contents) baseCommand: "echo" arguments: - "-n" - "foo" stdout: "step1_out"cwl_utils-0.41/cwl_utils/testdata/scatter-wf2_v1_0.cwl0000755000000000000000000000165713615410400017712 0ustar00#!/usr/bin/env cwl-runner cwlVersion: v1.0 class: Workflow inputs: inp1: string[] inp2: string[] outputs: out: outputSource: step1/echo_out type: type: array items: type: array items: string requirements: - class: ScatterFeatureRequirement steps: step1: in: echo_in1: inp1 echo_in2: inp2 out: [echo_out] scatter: [echo_in1, echo_in2] scatterMethod: nested_crossproduct run: class: CommandLineTool id: step1command inputs: echo_in1: type: string inputBinding: {} echo_in2: type: string inputBinding: {} outputs: echo_out: type: string outputBinding: glob: "step1_out" loadContents: true outputEval: $(self[0].contents) baseCommand: "echo" arguments: - "-n" - "foo" stdout: step1_out cwl_utils-0.41/cwl_utils/testdata/scatter-wf2_v1_1.cwl0000755000000000000000000000165613615410400017712 0ustar00#!/usr/bin/env cwl-runner cwlVersion: v1.1 class: Workflow inputs: inp1: string[] inp2: string[] outputs: out: outputSource: step1/echo_out type: type: array items: type: array items: string requirements: - class: ScatterFeatureRequirement steps: step1: in: echo_in1: inp1 echo_in2: inp2 out: [echo_out] scatter: [echo_in1, echo_in2] scatterMethod: nested_crossproduct run: class: CommandLineTool id: step1command inputs: echo_in1: type: string inputBinding: {} echo_in2: type: string inputBinding: {} outputs: echo_out: type: string outputBinding: glob: "step1_out" loadContents: true outputEval: $(self[0].contents) baseCommand: "echo" arguments: - "-n" - "foo" stdout: step1_outcwl_utils-0.41/cwl_utils/testdata/scatter-wf2_v1_2.cwl0000755000000000000000000000165613615410400017713 0ustar00#!/usr/bin/env cwl-runner cwlVersion: v1.2 class: Workflow inputs: inp1: string[] inp2: string[] outputs: out: outputSource: step1/echo_out type: type: array items: type: array items: string requirements: - class: ScatterFeatureRequirement steps: step1: in: echo_in1: inp1 echo_in2: inp2 out: [echo_out] scatter: [echo_in1, echo_in2] scatterMethod: nested_crossproduct run: class: CommandLineTool id: step1command inputs: echo_in1: type: string inputBinding: {} echo_in2: type: string inputBinding: {} outputs: echo_out: type: string outputBinding: glob: "step1_out" loadContents: true outputEval: $(self[0].contents) baseCommand: "echo" arguments: - "-n" - "foo" stdout: step1_outcwl_utils-0.41/cwl_utils/testdata/scatter-wf3_v1_0.cwl0000755000000000000000000000163213615410400017704 0ustar00#!/usr/bin/env cwl-runner cwlVersion: v1.0 $graph: - id: echo class: CommandLineTool hints: ResourceRequirement: ramMin: 8 inputs: echo_in1: type: string inputBinding: {} echo_in2: type: string inputBinding: {} outputs: echo_out: type: string outputBinding: glob: "step1_out" loadContents: true outputEval: $(self[0].contents) baseCommand: "echo" arguments: ["-n", "foo"] stdout: step1_out - id: main class: Workflow inputs: inp1: string[] inp2: string[] requirements: - class: ScatterFeatureRequirement steps: step1: scatter: [echo_in1, echo_in2] scatterMethod: flat_crossproduct in: echo_in1: inp1 echo_in2: inp2 out: [echo_out] run: "#echo" outputs: out: outputSource: step1/echo_out type: type: array items: stringcwl_utils-0.41/cwl_utils/testdata/scatter-wf3_v1_1.cwl0000755000000000000000000000155013615410400017704 0ustar00#!/usr/bin/env cwl-runner cwlVersion: v1.1 $graph: - id: echo class: CommandLineTool inputs: echo_in1: type: string inputBinding: {} echo_in2: type: string inputBinding: {} outputs: echo_out: type: string outputBinding: glob: "step1_out" loadContents: true outputEval: $(self[0].contents) baseCommand: "echo" arguments: ["-n", "foo"] stdout: step1_out - id: main class: Workflow inputs: inp1: string[] inp2: string[] requirements: - class: ScatterFeatureRequirement steps: step1: scatter: [echo_in1, echo_in2] scatterMethod: flat_crossproduct in: echo_in1: inp1 echo_in2: inp2 out: [echo_out] run: "#echo" outputs: out: outputSource: step1/echo_out type: type: array items: stringcwl_utils-0.41/cwl_utils/testdata/scatter-wf3_v1_2.cwl0000755000000000000000000000155013615410400017705 0ustar00#!/usr/bin/env cwl-runner cwlVersion: v1.2 $graph: - id: echo class: CommandLineTool inputs: echo_in1: type: string inputBinding: {} echo_in2: type: string inputBinding: {} outputs: echo_out: type: string outputBinding: glob: "step1_out" loadContents: true outputEval: $(self[0].contents) baseCommand: "echo" arguments: ["-n", "foo"] stdout: step1_out - id: main class: Workflow inputs: inp1: string[] inp2: string[] requirements: - class: ScatterFeatureRequirement steps: step1: scatter: [echo_in1, echo_in2] scatterMethod: flat_crossproduct in: echo_in1: inp1 echo_in2: inp2 out: [echo_out] run: "#echo" outputs: out: outputSource: step1/echo_out type: type: array items: stringcwl_utils-0.41/cwl_utils/testdata/seqtk_seq.cwl0000755000000000000000000000050413615410400016711 0ustar00#!/usr/bin/env cwl-runner cwlVersion: v1.0 class: CommandLineTool doc: "Convert to FASTA (seqtk)" baseCommand: ["seqtk", "seq"] inputs: sequences: type: File inputBinding: prefix: "-a" outputs: result: stdout hints: SoftwareRequirement: packages: - package: seqtk version: - r93 cwl_utils-0.41/cwl_utils/testdata/stage-array-job.json0000644000000000000000000000030613615410400020062 0ustar00{ "input_file": { "class": "File", "location": "whale.txt" }, "input_list": [ { "class": "File", "location": "hello.txt" } ] }cwl_utils-0.41/cwl_utils/testdata/stage-array.cwl0000755000000000000000000000124213615410400017131 0ustar00#!/usr/bin/env cwl-runner class: CommandLineTool cwlVersion: v1.2 id: stage_array arguments: - {shellQuote: false, valueFrom: "ls | grep -v lsout"} inputs: - id: input_file type: File - id: optional_file type: File? - id: input_list type: 'File[]' secondaryFiles: - ^.tar stdout: lsout outputs: - id: output type: File? outputBinding: glob: lsout label: stage-array.cwl requirements: - class: InitialWorkDirRequirement listing: - $(inputs.input_file) - $(inputs.optional_file) - entry: $(inputs.input_list) - entry: $(null) - entryname: a entry: b - class: ShellCommandRequirement cwl_utils-0.41/cwl_utils/testdata/stdout-wf_v1_0.cwl0000755000000000000000000000041013615410400017467 0ustar00#!/usr/bin/env cwl-runner class: Workflow cwlVersion: v1.0 inputs: letters0: type: string default: "a0" outputs: all: type: File outputSource: echo_w/txt steps: echo_w: run: echo_v1_0.cwl in: echo_in: letters0 out: [txt] cwl_utils-0.41/cwl_utils/testdata/stdout-wf_v1_1.cwl0000755000000000000000000000041013615410400017470 0ustar00#!/usr/bin/env cwl-runner class: Workflow cwlVersion: v1.1 inputs: letters0: type: string default: "a0" outputs: all: type: File outputSource: echo_w/txt steps: echo_w: run: echo_v1_1.cwl in: echo_in: letters0 out: [txt] cwl_utils-0.41/cwl_utils/testdata/stdout-wf_v1_2.cwl0000755000000000000000000000041013615410400017471 0ustar00#!/usr/bin/env cwl-runner class: Workflow cwlVersion: v1.2 inputs: letters0: type: string default: "a0" outputs: all: type: File outputSource: echo_w/txt steps: echo_w: run: echo_v1_2.cwl in: echo_in: letters0 out: [txt] cwl_utils-0.41/cwl_utils/testdata/step-valuefrom2-wf_v1_0.cwl0000755000000000000000000000140413615410400021204 0ustar00#!/usr/bin/env cwl-runner class: Workflow cwlVersion: v1.0 requirements: - class: StepInputExpressionRequirement - class: InlineJavascriptRequirement - class: MultipleInputFeatureRequirement inputs: a: int b: int outputs: val: type: string outputSource: step1/echo_out steps: step1: run: id: echo class: CommandLineTool inputs: c: type: int inputBinding: {} outputs: echo_out: type: string outputBinding: glob: "step1_out" loadContents: true outputEval: $(self[0].contents) baseCommand: "echo" stdout: step1_out in: c: source: [a, b] valueFrom: "$(self[0] + self[1])" out: [echo_out] cwl_utils-0.41/cwl_utils/testdata/step-valuefrom2-wf_v1_1.cwl0000755000000000000000000000140413615410400021205 0ustar00#!/usr/bin/env cwl-runner class: Workflow cwlVersion: v1.1 requirements: - class: StepInputExpressionRequirement - class: InlineJavascriptRequirement - class: MultipleInputFeatureRequirement inputs: a: int b: int outputs: val: type: string outputSource: step1/echo_out steps: step1: run: id: echo class: CommandLineTool inputs: c: type: int inputBinding: {} outputs: echo_out: type: string outputBinding: glob: "step1_out" loadContents: true outputEval: $(self[0].contents) baseCommand: "echo" stdout: step1_out in: c: source: [a, b] valueFrom: "$(self[0] + self[1])" out: [echo_out] cwl_utils-0.41/cwl_utils/testdata/step-valuefrom2-wf_v1_2.cwl0000755000000000000000000000140413615410400021206 0ustar00#!/usr/bin/env cwl-runner class: Workflow cwlVersion: v1.2 requirements: - class: StepInputExpressionRequirement - class: InlineJavascriptRequirement - class: MultipleInputFeatureRequirement inputs: a: int b: int outputs: val: type: string outputSource: step1/echo_out steps: step1: run: id: echo class: CommandLineTool inputs: c: type: int inputBinding: {} outputs: echo_out: type: string outputBinding: glob: "step1_out" loadContents: true outputEval: $(self[0].contents) baseCommand: "echo" stdout: step1_out in: c: source: [a, b] valueFrom: "$(self[0] + self[1])" out: [echo_out] cwl_utils-0.41/cwl_utils/testdata/step-valuefrom3-wf_v1_0.cwl0000755000000000000000000000133213615410400021205 0ustar00#!/usr/bin/env cwl-runner class: Workflow cwlVersion: v1.0 requirements: - class: StepInputExpressionRequirement - class: InlineJavascriptRequirement inputs: a: int b: int outputs: val: type: string outputSource: step1/echo_out steps: step1: run: id: echo class: CommandLineTool inputs: c: type: int inputBinding: {} outputs: echo_out: type: string outputBinding: glob: "step1_out" loadContents: true outputEval: $(self[0].contents) baseCommand: "echo" stdout: step1_out in: a: a b: b c: valueFrom: "$(inputs.a + inputs.b)" out: [echo_out] cwl_utils-0.41/cwl_utils/testdata/step-valuefrom3-wf_v1_1.cwl0000755000000000000000000000133213615410400021206 0ustar00#!/usr/bin/env cwl-runner class: Workflow cwlVersion: v1.1 requirements: - class: StepInputExpressionRequirement - class: InlineJavascriptRequirement inputs: a: int b: int outputs: val: type: string outputSource: step1/echo_out steps: step1: run: id: echo class: CommandLineTool inputs: c: type: int inputBinding: {} outputs: echo_out: type: string outputBinding: glob: "step1_out" loadContents: true outputEval: $(self[0].contents) baseCommand: "echo" stdout: step1_out in: a: a b: b c: valueFrom: "$(inputs.a + inputs.b)" out: [echo_out] cwl_utils-0.41/cwl_utils/testdata/step-valuefrom3-wf_v1_2.cwl0000755000000000000000000000133213615410400021207 0ustar00#!/usr/bin/env cwl-runner class: Workflow cwlVersion: v1.2 requirements: - class: StepInputExpressionRequirement - class: InlineJavascriptRequirement inputs: a: int b: int outputs: val: type: string outputSource: step1/echo_out steps: step1: run: id: echo class: CommandLineTool inputs: c: type: int inputBinding: {} outputs: echo_out: type: string outputBinding: glob: "step1_out" loadContents: true outputEval: $(self[0].contents) baseCommand: "echo" stdout: step1_out in: a: a b: b c: valueFrom: "$(inputs.a + inputs.b)" out: [echo_out] cwl_utils-0.41/cwl_utils/testdata/step_valuefrom5_wf_v1_0.cwl0000755000000000000000000000244113615410400021355 0ustar00#!/usr/bin/env cwl-runner class: Workflow cwlVersion: v1.0 requirements: StepInputExpressionRequirement: {} inputs: file1: File outputs: val1: type: string outputSource: step1/echo_out val2: type: string outputSource: step2/echo_out steps: step1: run: class: CommandLineTool inputs: name: type: string inputBinding: {} outputs: echo_out: type: string outputBinding: glob: step1_out loadContents: true outputEval: $(self[0].contents) echo_out_file: type: File outputBinding: glob: step1_out baseCommand: echo stdout: step1_out in: name: source: file1 valueFrom: $(self.basename) out: [echo_out, echo_out_file] step2: run: class: CommandLineTool inputs: name: type: string inputBinding: {} outputs: echo_out: type: string outputBinding: glob: step1_out loadContents: true outputEval: $(self[0].contents) baseCommand: echo stdout: step1_out in: name: source: step1/echo_out_file valueFrom: $(self.basename) out: [echo_out] cwl_utils-0.41/cwl_utils/testdata/step_valuefrom5_wf_v1_1.cwl0000755000000000000000000000244113615410400021356 0ustar00#!/usr/bin/env cwl-runner class: Workflow cwlVersion: v1.1 requirements: StepInputExpressionRequirement: {} inputs: file1: File outputs: val1: type: string outputSource: step1/echo_out val2: type: string outputSource: step2/echo_out steps: step1: run: class: CommandLineTool inputs: name: type: string inputBinding: {} outputs: echo_out: type: string outputBinding: glob: step1_out loadContents: true outputEval: $(self[0].contents) echo_out_file: type: File outputBinding: glob: step1_out baseCommand: echo stdout: step1_out in: name: source: file1 valueFrom: $(self.basename) out: [echo_out, echo_out_file] step2: run: class: CommandLineTool inputs: name: type: string inputBinding: {} outputs: echo_out: type: string outputBinding: glob: step1_out loadContents: true outputEval: $(self[0].contents) baseCommand: echo stdout: step1_out in: name: source: step1/echo_out_file valueFrom: $(self.basename) out: [echo_out] cwl_utils-0.41/cwl_utils/testdata/step_valuefrom5_wf_v1_2.cwl0000755000000000000000000000244113615410400021357 0ustar00#!/usr/bin/env cwl-runner class: Workflow cwlVersion: v1.2 requirements: StepInputExpressionRequirement: {} inputs: file1: File outputs: val1: type: string outputSource: step1/echo_out val2: type: string outputSource: step2/echo_out steps: step1: run: class: CommandLineTool inputs: name: type: string inputBinding: {} outputs: echo_out: type: string outputBinding: glob: step1_out loadContents: true outputEval: $(self[0].contents) echo_out_file: type: File outputBinding: glob: step1_out baseCommand: echo stdout: step1_out in: name: source: file1 valueFrom: $(self.basename) out: [echo_out, echo_out_file] step2: run: class: CommandLineTool inputs: name: type: string inputBinding: {} outputs: echo_out: type: string outputBinding: glob: step1_out loadContents: true outputEval: $(self[0].contents) baseCommand: echo stdout: step1_out in: name: source: step1/echo_out_file valueFrom: $(self.basename) out: [echo_out] cwl_utils-0.41/cwl_utils/testdata/step_valuefrom5_wf_with_id_v1_0.cwl0000755000000000000000000000246713615410400023074 0ustar00#!/usr/bin/env cwl-runner class: Workflow cwlVersion: v1.0 requirements: StepInputExpressionRequirement: {} inputs: file1: File outputs: val1: type: string outputSource: step1/echo_out val2: type: string outputSource: step2/echo_out steps: step1: run: id: explicit/id class: CommandLineTool inputs: name: type: string inputBinding: {} outputs: echo_out: type: string outputBinding: glob: step1_out loadContents: true outputEval: $(self[0].contents) echo_out_file: type: File outputBinding: glob: step1_out baseCommand: echo stdout: step1_out in: name: source: file1 valueFrom: $(self.basename) out: [echo_out, echo_out_file] step2: run: class: CommandLineTool inputs: name: type: string inputBinding: {} outputs: echo_out: type: string outputBinding: glob: step1_out loadContents: true outputEval: $(self[0].contents) baseCommand: echo stdout: step1_out in: name: source: step1/echo_out_file valueFrom: $(self.basename) out: [echo_out] cwl_utils-0.41/cwl_utils/testdata/step_valuefrom5_wf_with_id_v1_1.cwl0000755000000000000000000000246713615410400023075 0ustar00#!/usr/bin/env cwl-runner class: Workflow cwlVersion: v1.1 requirements: StepInputExpressionRequirement: {} inputs: file1: File outputs: val1: type: string outputSource: step1/echo_out val2: type: string outputSource: step2/echo_out steps: step1: run: id: explicit/id class: CommandLineTool inputs: name: type: string inputBinding: {} outputs: echo_out: type: string outputBinding: glob: step1_out loadContents: true outputEval: $(self[0].contents) echo_out_file: type: File outputBinding: glob: step1_out baseCommand: echo stdout: step1_out in: name: source: file1 valueFrom: $(self.basename) out: [echo_out, echo_out_file] step2: run: class: CommandLineTool inputs: name: type: string inputBinding: {} outputs: echo_out: type: string outputBinding: glob: step1_out loadContents: true outputEval: $(self[0].contents) baseCommand: echo stdout: step1_out in: name: source: step1/echo_out_file valueFrom: $(self.basename) out: [echo_out] cwl_utils-0.41/cwl_utils/testdata/step_valuefrom5_wf_with_id_v1_2.cwl0000755000000000000000000000246713615410400023076 0ustar00#!/usr/bin/env cwl-runner class: Workflow cwlVersion: v1.2 requirements: StepInputExpressionRequirement: {} inputs: file1: File outputs: val1: type: string outputSource: step1/echo_out val2: type: string outputSource: step2/echo_out steps: step1: run: id: explicit/id class: CommandLineTool inputs: name: type: string inputBinding: {} outputs: echo_out: type: string outputBinding: glob: step1_out loadContents: true outputEval: $(self[0].contents) echo_out_file: type: File outputBinding: glob: step1_out baseCommand: echo stdout: step1_out in: name: source: file1 valueFrom: $(self.basename) out: [echo_out, echo_out_file] step2: run: class: CommandLineTool inputs: name: type: string inputBinding: {} outputs: echo_out: type: string outputBinding: glob: step1_out loadContents: true outputEval: $(self[0].contents) baseCommand: echo stdout: step1_out in: name: source: step1/echo_out_file valueFrom: $(self.basename) out: [echo_out] cwl_utils-0.41/cwl_utils/testdata/wc3-tool_v1_0.cwl0000755000000000000000000000100213615410400017200 0ustar00#!/usr/bin/env cwl-runner class: CommandLineTool cwlVersion: v1.0 requirements: - class: InlineJavascriptRequirement hints: ResourceRequirement: ramMin: 8 inputs: file1: type: File[] inputBinding: {} outputs: output: type: int outputBinding: glob: output.txt loadContents: true outputEval: | ${ var s = self[0].contents.split(/\r?\n/); return parseInt(s[s.length-2]); } stdout: output.txtcwl_utils-0.41/cwl_utils/testdata/wc3-tool_v1_1.cwl0000755000000000000000000000074613615410400017217 0ustar00#!/usr/bin/env cwl-runner class: CommandLineTool cwlVersion: v1.1 requirements: - class: InlineJavascriptRequirement inputs: file1: type: File[] inputBinding: {} outputs: output: type: int outputBinding: glob: output.txt loadContents: true outputEval: | ${ var s = self[0].contents.split(/\r?\n/); return parseInt(s[s.length-2]); } stdout: output.txt baseCommand: wccwl_utils-0.41/cwl_utils/testdata/wc3-tool_v1_2.cwl0000755000000000000000000000074613615410400017220 0ustar00#!/usr/bin/env cwl-runner class: CommandLineTool cwlVersion: v1.2 requirements: - class: InlineJavascriptRequirement inputs: file1: type: File[] inputBinding: {} outputs: output: type: int outputBinding: glob: output.txt loadContents: true outputEval: | ${ var s = self[0].contents.split(/\r?\n/); return parseInt(s[s.length-2]); } stdout: output.txt baseCommand: wccwl_utils-0.41/cwl_utils/testdata/wf2.cwl0000755000000000000000000000075613615410400015421 0ustar00#!/usr/bin/env cwl-runner class: Workflow cwlVersion: v1.2 inputs: in1: types/testtypes.yml#my_boolean_array in2: type: types/testtypes.yml#my_enum steps: s1: run: remote-cwl/wf1.cwl in: - id: in1 source: "#in1" out: [out1] s2: run: remote-cwl/tool1.cwl in: in1: s1/out1 out: [out1] outputs: out1: type: string outputSource: "#s2/out1" requirements: SchemaDefRequirement: types: - $import: types/testtypes.yml cwl_utils-0.41/cwl_utils/testdata/workflow_input_format_expr.cwl0000755000000000000000000000124513615410400022414 0ustar00#!/usr/bin/env cwl-runner cwlVersion: v1.0 class: Workflow requirements: InlineJavascriptRequirement: {} inputs: first: type: File format: | ${ return "http://edamontology.org/format_3016"; } default: class: File basename: default format: http://edamontology.org/format_3016 contents: "42" steps: format_extract: in: target: first run: class: ExpressionTool inputs: target: File expression: | ${ return {"result": inputs.target.format}; } outputs: result: string out: [ result ] outputs: format_uri: type: string outputSource: format_extract/result cwl_utils-0.41/cwl_utils/testdata/workflow_input_format_expr_v1_1.cwl0000755000000000000000000000124513615410400023242 0ustar00#!/usr/bin/env cwl-runner cwlVersion: v1.1 class: Workflow requirements: InlineJavascriptRequirement: {} inputs: first: type: File format: | ${ return "http://edamontology.org/format_3016"; } default: class: File basename: default format: http://edamontology.org/format_3016 contents: "42" steps: format_extract: in: target: first run: class: ExpressionTool inputs: target: File expression: | ${ return {"result": inputs.target.format}; } outputs: result: string out: [ result ] outputs: format_uri: type: string outputSource: format_extract/result cwl_utils-0.41/cwl_utils/testdata/workflow_input_format_expr_v1_2.cwl0000755000000000000000000000124513615410400023243 0ustar00#!/usr/bin/env cwl-runner cwlVersion: v1.2 class: Workflow requirements: InlineJavascriptRequirement: {} inputs: first: type: File format: | ${ return "http://edamontology.org/format_3016"; } default: class: File basename: default format: http://edamontology.org/format_3016 contents: "42" steps: format_extract: in: target: first run: class: ExpressionTool inputs: target: File expression: | ${ return {"result": inputs.target.format}; } outputs: result: string out: [ result ] outputs: format_uri: type: string outputSource: format_extract/result cwl_utils-0.41/cwl_utils/testdata/workflow_input_sf_expr.cwl0000755000000000000000000000133113615410400021530 0ustar00#!/usr/bin/env cwl-runner cwlVersion: v1.0 class: Workflow requirements: InlineJavascriptRequirement: {} inputs: first: type: File secondaryFiles: | ${ return self.basename+".2"; } default: class: File basename: default.txt contents: "42" secondaryFiles: - class: File basename: default.txt.2 contents: "23" steps: sf_extract: in: target: first run: class: ExpressionTool inputs: target: File expression: | ${ return {"result": inputs.target.secondaryFiles[0].basename}; } outputs: result: string out: [ result ] outputs: sf_name: type: string outputSource: sf_extract/result cwl_utils-0.41/cwl_utils/testdata/workflow_input_sf_expr_array.cwl0000755000000000000000000000133113615410400022726 0ustar00#!/usr/bin/env cwl-runner cwlVersion: v1.0 class: Workflow requirements: InlineJavascriptRequirement: {} inputs: first: type: File secondaryFiles: - ${ return self.basename+".2"; } default: class: File basename: default.txt contents: "42" secondaryFiles: - class: File basename: default.txt.2 contents: "23" steps: sf_extract: in: target: first run: class: ExpressionTool inputs: target: File expression: | ${ return {"result": inputs.target.secondaryFiles[0].basename}; } outputs: result: string out: [ result ] outputs: sf_name: type: string outputSource: sf_extract/result cwl_utils-0.41/cwl_utils/testdata/workflow_input_sf_expr_array_v1_1.cwl0000755000000000000000000000133113615410400023554 0ustar00#!/usr/bin/env cwl-runner cwlVersion: v1.1 class: Workflow requirements: InlineJavascriptRequirement: {} inputs: first: type: File secondaryFiles: - ${ return self.basename+".2"; } default: class: File basename: default.txt contents: "42" secondaryFiles: - class: File basename: default.txt.2 contents: "23" steps: sf_extract: in: target: first run: class: ExpressionTool inputs: target: File expression: | ${ return {"result": inputs.target.secondaryFiles[0].basename}; } outputs: result: string out: [ result ] outputs: sf_name: type: string outputSource: sf_extract/result cwl_utils-0.41/cwl_utils/testdata/workflow_input_sf_expr_array_v1_2.cwl0000755000000000000000000000134313615410400023560 0ustar00#!/usr/bin/env cwl-runner cwlVersion: v1.2 class: Workflow requirements: InlineJavascriptRequirement: {} inputs: first: type: File secondaryFiles: - | ${ return self.basename+".2"; } default: class: File basename: default.txt contents: "42" secondaryFiles: - class: File basename: default.txt.2 contents: "23" steps: sf_extract: in: target: first run: class: ExpressionTool inputs: target: File expression: | ${ return {"result": inputs.target.secondaryFiles[0].basename}; } outputs: result: string out: [ result ] outputs: sf_name: type: string outputSource: sf_extract/result cwl_utils-0.41/cwl_utils/testdata/workflow_input_sf_expr_v1_1.cwl0000755000000000000000000000133113615410400022356 0ustar00#!/usr/bin/env cwl-runner cwlVersion: v1.1 class: Workflow requirements: InlineJavascriptRequirement: {} inputs: first: type: File secondaryFiles: | ${ return self.basename+".2"; } default: class: File basename: default.txt contents: "42" secondaryFiles: - class: File basename: default.txt.2 contents: "23" steps: sf_extract: in: target: first run: class: ExpressionTool inputs: target: File expression: | ${ return {"result": inputs.target.secondaryFiles[0].basename}; } outputs: result: string out: [ result ] outputs: sf_name: type: string outputSource: sf_extract/result cwl_utils-0.41/cwl_utils/testdata/workflow_input_sf_expr_v1_2.cwl0000755000000000000000000000133113615410400022357 0ustar00#!/usr/bin/env cwl-runner cwlVersion: v1.2 class: Workflow requirements: InlineJavascriptRequirement: {} inputs: first: type: File secondaryFiles: | ${ return self.basename+".2"; } default: class: File basename: default.txt contents: "42" secondaryFiles: - class: File basename: default.txt.2 contents: "23" steps: sf_extract: in: target: first run: class: ExpressionTool inputs: target: File expression: | ${ return {"result": inputs.target.secondaryFiles[0].basename}; } outputs: result: string out: [ result ] outputs: sf_name: type: string outputSource: sf_extract/result cwl_utils-0.41/cwl_utils/testdata/checker_wf/broken-wf.cwl0000755000000000000000000000251613615410400020711 0ustar00#!/usr/bin/env cwl-runner class: Workflow cwlVersion: v1.0 requirements: ScatterFeatureRequirement: {} MultipleInputFeatureRequirement: {} StepInputExpressionRequirement: {} inputs: letters0: type: [string, int] default: "a0" letters1: type: string[] default: ["a1", "b1"] letters2: type: [string, int] default: "a2" letters3: type: string[] default: ["a3", "b3"] letters4: type: int default: 4 letters5: type: string[] default: ["a5", "b5", "c5"] outputs: all: type: File[] outputSource: cat/txt steps: echo_v: run: echo.cwl in: echo_in: {} out: [txt] echo_w: run: echo.cwl in: echo_in: letters0 out: [txt] echo_x: run: echo.cwl scatter: echo_in in: echo_in: source: [letters1, letters2] linkMerge: merge_nested out: [txt] echo_y: run: echo.cwl scatter: echo_in in: echo_in: source: [letters3, letters4] linkMerge: merge_flattened out: [txt] echo_z: run: echo.cwl in: echo_in: source: letters5 valueFrom: "special value parsed in valueFrom" out: [txt] cat: run: cat.cwl in: cat_in: source: [echo_w/txt, echo_x/txt, echo_y/txt, echo_z/txt, letters0] linkMerge: merge_flattened out: [txt] cwl_utils-0.41/cwl_utils/testdata/checker_wf/broken-wf2.cwl0000755000000000000000000000250613615410400020772 0ustar00#!/usr/bin/env cwl-runner class: Workflow cwlVersion: v1.0 requirements: ScatterFeatureRequirement: {} MultipleInputFeatureRequirement: {} StepInputExpressionRequirement: {} inputs: letters0: type: [string, int] default: "a0" letters1: type: string[] default: ["a1", "b1"] letters2: type: [string, int] default: "a2" letters3: type: string[] default: ["a3", "b3"] letters4: type: int default: 4 letters5: type: string[] default: ["a5", "b5", "c5"] outputs: all: type: File[] outputSource: cat/txt steps: echo_v: run: echo.cwl in: {} out: [txt] echo_w: run: echo.cwl in: echo_in: letters0 out: [txt, other] echo_x: run: echo.cwl scatter: echo_in in: echo_in: source: [letters1, letters2] linkMerge: merge_nested out: [txt] echo_y: run: echo.cwl scatter: echo_in in: echo_in: source: [letters3, letters4] linkMerge: merge_flattened out: [txt] echo_z: run: echo.cwl in: echo_in: source: letters5 valueFrom: "special value parsed in valueFrom" out: [txt] cat: run: cat.cwl in: cat_in: source: [echo_w/txt, echo_x/txt, echo_y/txt, echo_z/txt, letters0] linkMerge: merge_flattened out: [txt] cwl_utils-0.41/cwl_utils/testdata/checker_wf/broken-wf3.cwl0000755000000000000000000000141013615410400020764 0ustar00#!/usr/bin/env cwl-runner class: Workflow cwlVersion: v1.0 requirements: ScatterFeatureRequirement: {} MultipleInputFeatureRequirement: {} StepInputExpressionRequirement: {} inputs: letters0: type: [string, int] default: "a0" letters1: type: string[] default: ["a1", "b1"] letters2: type: [string, int] default: "a2" letters3: type: string[] default: ["a3", "b3"] letters4: type: string default: "a4" letters5: type: string[] default: ["a5", "b5", "c5"] outputs: all: type: File outputSource: cat/txt steps: - id: embedded run: functional-wf.cwl in: [] out: - id: All - id: cat run: cat.cwl in: - id: cat_in source: - embedded/All out: [txt] cwl_utils-0.41/cwl_utils/testdata/checker_wf/cat.cwl0000755000000000000000000000027413615410400017565 0ustar00#!/usr/bin/env cwl-runner cwlVersion: v1.0 class: CommandLineTool baseCommand: cat inputs: cat_in: type: File[] inputBinding: {} stdout: all.txt outputs: txt: type: stdout cwl_utils-0.41/cwl_utils/testdata/checker_wf/echo.cwl0000755000000000000000000000032713615410400017733 0ustar00#!/usr/bin/env cwl-runner cwlVersion: v1.0 class: CommandLineTool baseCommand: echo inputs: echo_in: type: - string - string[] inputBinding: {} stdout: out.txt outputs: txt: type: stdout cwl_utils-0.41/cwl_utils/testdata/checker_wf/functional-wf.cwl0000755000000000000000000000240313615410400021566 0ustar00#!/usr/bin/env cwl-runner class: Workflow cwlVersion: v1.0 requirements: ScatterFeatureRequirement: {} MultipleInputFeatureRequirement: {} StepInputExpressionRequirement: {} inputs: letters0: type: [string, int] default: "a0" letters1: type: string[] default: ["a1", "b1"] letters2: type: [string, int] default: "a2" letters3: type: string[] default: ["a3", "b3"] letters4: type: string default: "a4" letters5: type: string[] default: ["a5", "b5", "c5"] outputs: all: type: File outputSource: cat/txt steps: echo_w: run: echo.cwl in: echo_in: letters0 out: [txt] echo_x: run: echo.cwl scatter: echo_in in: echo_in: source: [letters1, letters2] linkMerge: merge_nested out: [txt] echo_y: run: echo.cwl scatter: echo_in in: echo_in: source: [letters3, letters4] linkMerge: merge_flattened out: [txt] echo_z: run: echo.cwl in: echo_in: source: letters5 valueFrom: "special value parsed in valueFrom" out: [txt] cat: run: cat.cwl in: cat_in: source: [echo_w/txt, echo_x/txt, echo_y/txt, echo_z/txt] linkMerge: merge_flattened out: [txt] cwl_utils-0.41/cwl_utils/testdata/checker_wf/no-warning-wf.cwl0000755000000000000000000000134313615410400021505 0ustar00#!/usr/bin/env cwl-runner class: Workflow cwlVersion: v1.2 requirements: ScatterFeatureRequirement: {} MultipleInputFeatureRequirement: {} StepInputExpressionRequirement: {} inputs: letters0: type: [string, int] default: "a0" letters1: type: string[] default: ["a1", "b1"] letters2: type: [string, int] default: "a2" letters3: type: string[] default: ["a3", "b3"] letters4: type: string default: "a4" letters5: type: string[] default: ["a5", "b5", "c5"] exec: type: bool default: False outputs: single: type: File? outputSource: - step1/txt steps: - id: step1 run: echo.cwl in: exec: exec out: [txt] when: $(inputs.exec) cwl_utils-0.41/cwl_utils/testdata/checker_wf/warning-wf.cwl0000755000000000000000000000134213615410400021072 0ustar00#!/usr/bin/env cwl-runner class: Workflow cwlVersion: v1.2 requirements: ScatterFeatureRequirement: {} MultipleInputFeatureRequirement: {} StepInputExpressionRequirement: {} inputs: letters0: type: [string, int] default: "a0" letters1: type: string[] default: ["a1", "b1"] letters2: type: [string, int] default: "a2" letters3: type: string[] default: ["a3", "b3"] letters4: type: string default: "a4" letters5: type: string[] default: ["a5", "b5", "c5"] exec: type: bool default: False outputs: single: type: File outputSource: - step1/txt steps: - id: step1 run: echo.cwl in: exec: exec out: [txt] when: $(inputs.exec) cwl_utils-0.41/cwl_utils/testdata/checker_wf/warning-wf2.cwl0000755000000000000000000000133513615410400021156 0ustar00#!/usr/bin/env cwl-runner class: Workflow cwlVersion: v1.2 requirements: ScatterFeatureRequirement: {} MultipleInputFeatureRequirement: {} StepInputExpressionRequirement: {} inputs: letters0: type: [string, int] default: "a0" letters1: type: string[] default: ["a1", "b1"] letters2: type: [string, int] default: "a2" letters3: type: string[] default: ["a3", "b3"] letters4: type: string default: "a4" letters5: type: string[] default: ["a5", "b5", "c5"] exec: type: bool default: False outputs: single_a: type: File outputSource: step1/txt steps: - id: step1 run: echo.cwl in: exec: exec out: [txt] when: $(inputs.exec) cwl_utils-0.41/cwl_utils/testdata/checker_wf/warning-wf3.cwl0000755000000000000000000000150613615410400021157 0ustar00#!/usr/bin/env cwl-runner class: Workflow cwlVersion: v1.2 requirements: ScatterFeatureRequirement: {} MultipleInputFeatureRequirement: {} StepInputExpressionRequirement: {} inputs: letters0: type: [string, int] default: "a0" letters1: type: string[] default: ["a1", "b1"] letters2: type: [string, int] default: "a2" letters3: type: string[] default: ["a3", "b3"] letters4: type: string default: "a4" letters5: type: string[] default: ["a5", "b5", "c5"] exec: type: bool default: False outputs: pair: type: File[] outputSource: - step1/txt - step2/txt steps: - id: step1 run: echo.cwl in: exec: exec out: [txt] when: $(inputs.exec) - id: step2 run: echo.cwl in: [] out: [txt] when: $(inputs.exec) cwl_utils-0.41/cwl_utils/testdata/extensions/all-output-loop_v1_2.cwl0000755000000000000000000000111713615410400023016 0ustar00#!/usr/bin/env cwl-runner cwlVersion: v1.2 class: Workflow $namespaces: cwltool: "http://commonwl.org/cwltool#" requirements: InlineJavascriptRequirement: {} inputs: i1: int outputs: o1: type: int[] outputSource: subworkflow/o1 steps: subworkflow: run: class: ExpressionTool inputs: i1: int outputs: o1: int expression: > ${return {'o1': inputs.i1 + 1};} in: i1: i1 out: [o1] requirements: cwltool:Loop: loopWhen: $(inputs.i1 < 10) loop: i1: o1 outputMethod: all cwl_utils-0.41/cwl_utils/testdata/extensions/cuda-requirement_v1_0.cwl0000755000000000000000000000052613615410400023214 0ustar00#!/usr/bin/env cwl-runner cwlVersion: v1.0 class: CommandLineTool $namespaces: cwltool: "http://commonwl.org/cwltool#" requirements: cwltool:CUDARequirement: cudaVersionMin: "1.0" cudaComputeCapability: "1.0" cudaDeviceCountMin: $(inputs.gpus) inputs: gpus: type: int default: 1 outputs: [] baseCommand: "nvidia-smi"cwl_utils-0.41/cwl_utils/testdata/extensions/cuda-requirement_v1_1.cwl0000755000000000000000000000052613615410400023215 0ustar00#!/usr/bin/env cwl-runner cwlVersion: v1.1 class: CommandLineTool $namespaces: cwltool: "http://commonwl.org/cwltool#" requirements: cwltool:CUDARequirement: cudaVersionMin: "1.0" cudaComputeCapability: "1.0" cudaDeviceCountMin: $(inputs.gpus) inputs: gpus: type: int default: 1 outputs: [] baseCommand: "nvidia-smi"cwl_utils-0.41/cwl_utils/testdata/extensions/cuda-requirement_v1_2.cwl0000755000000000000000000000052613615410400023216 0ustar00#!/usr/bin/env cwl-runner cwlVersion: v1.2 class: CommandLineTool $namespaces: cwltool: "http://commonwl.org/cwltool#" requirements: cwltool:CUDARequirement: cudaVersionMin: "1.0" cudaComputeCapability: "1.0" cudaDeviceCountMin: $(inputs.gpus) inputs: gpus: type: int default: 1 outputs: [] baseCommand: "nvidia-smi"cwl_utils-0.41/cwl_utils/testdata/extensions/inplace-update-requirement_v1_0.cwl0000755000000000000000000000067013615410400025173 0ustar00#!/usr/bin/env cwl-runner class: CommandLineTool cwlVersion: v1.0 $namespaces: cwltool: "http://commonwl.org/cwltool#" requirements: cwltool:InplaceUpdateRequirement: inplaceUpdate: true inputs: r: File script: type: File default: class: File location: updateval.py outputs: out: type: File outputBinding: glob: $(inputs.r.basename) arguments: [python, $(inputs.script), $(inputs.r.basename)]cwl_utils-0.41/cwl_utils/testdata/extensions/load-listing-requirement_v1_0.cwl0000755000000000000000000000044413615410400024665 0ustar00#!/usr/bin/env cwl-runner class: CommandLineTool cwlVersion: v1.0 $namespaces: cwltool: http://commonwl.org/cwltool# requirements: cwltool:LoadListingRequirement: loadListing: shallow_listing inputs: d: Directory outputs: [] arguments: [echo, "$(inputs.d.listing[0].listing[0])"] cwl_utils-0.41/cwl_utils/testdata/extensions/mpi-requirement_v1_0.cwl0000755000000000000000000000036713615410400023070 0ustar00#!/usr/bin/env cwl-runner class: CommandLineTool cwlVersion: v1.0 $namespaces: cwltool: "http://commonwl.org/cwltool#" baseCommand: env requirements: cwltool:MPIRequirement: processes: 1 inputs: {} outputs: environment: type: stdoutcwl_utils-0.41/cwl_utils/testdata/extensions/mpi-requirement_v1_1.cwl0000755000000000000000000000036613615410400023070 0ustar00#!/usr/bin/env cwl-runner class: CommandLineTool cwlVersion: v1.1 $namespaces: cwltool: "http://commonwl.org/cwltool#" baseCommand: env requirements: cwltool:MPIRequirement: processes: 1 inputs: {} outputs: environment: type: stdoutcwl_utils-0.41/cwl_utils/testdata/extensions/mpi-requirement_v1_2.cwl0000755000000000000000000000036613615410400023071 0ustar00#!/usr/bin/env cwl-runner class: CommandLineTool cwlVersion: v1.2 $namespaces: cwltool: "http://commonwl.org/cwltool#" baseCommand: env requirements: cwltool:MPIRequirement: processes: 1 inputs: {} outputs: environment: type: stdoutcwl_utils-0.41/cwl_utils/testdata/extensions/network-access_v1_0.cwl0000755000000000000000000000055313615410400022672 0ustar00#!/usr/bin/env cwl-runner class: CommandLineTool cwlVersion: v1.0 $namespaces: cwltool: "http://commonwl.org/cwltool#" requirements: cwltool:NetworkAccess: networkAccess: true inputs: [] outputs: [] baseCommand: python arguments: - "-c" - valueFrom: | import urllib.request assert(urllib.request.urlopen("http://commonwl.org").code == 200)cwl_utils-0.41/cwl_utils/testdata/extensions/process-generator_v1_0.cwl0000755000000000000000000000127513615410400023406 0ustar00#!/usr/bin/env cwl-runner cwlVersion: v1.0 $namespaces: cwltool: "http://commonwl.org/cwltool#" class: cwltool:ProcessGenerator inputs: script: string dir: Directory outputs: {} run: class: CommandLineTool inputs: script: string dir: Directory outputs: runProcess: type: File outputBinding: glob: main.cwl requirements: InlineJavascriptRequirement: {} LoadListingRequirement: loadListing: shallow_listing InitialWorkDirRequirement: listing: | ${ var v = inputs.dir.listing; v.push({entryname: "inp.py", entry: inputs.script}); return v; } arguments: [python3, inp.py] stdout: main.cwlcwl_utils-0.41/cwl_utils/testdata/extensions/process-generator_v1_1.cwl0000755000000000000000000000127513615410400023407 0ustar00#!/usr/bin/env cwl-runner cwlVersion: v1.1 $namespaces: cwltool: "http://commonwl.org/cwltool#" class: cwltool:ProcessGenerator inputs: script: string dir: Directory outputs: {} run: class: CommandLineTool inputs: script: string dir: Directory outputs: runProcess: type: File outputBinding: glob: main.cwl requirements: InlineJavascriptRequirement: {} LoadListingRequirement: loadListing: shallow_listing InitialWorkDirRequirement: listing: | ${ var v = inputs.dir.listing; v.push({entryname: "inp.py", entry: inputs.script}); return v; } arguments: [python3, inp.py] stdout: main.cwlcwl_utils-0.41/cwl_utils/testdata/extensions/process-generator_v1_2.cwl0000755000000000000000000000127513615410400023410 0ustar00#!/usr/bin/env cwl-runner cwlVersion: v1.2 $namespaces: cwltool: "http://commonwl.org/cwltool#" class: cwltool:ProcessGenerator inputs: script: string dir: Directory outputs: {} run: class: CommandLineTool inputs: script: string dir: Directory outputs: runProcess: type: File outputBinding: glob: main.cwl requirements: InlineJavascriptRequirement: {} LoadListingRequirement: loadListing: shallow_listing InitialWorkDirRequirement: listing: | ${ var v = inputs.dir.listing; v.push({entryname: "inp.py", entry: inputs.script}); return v; } arguments: [python3, inp.py] stdout: main.cwlcwl_utils-0.41/cwl_utils/testdata/extensions/secrets_v1_0.cwl0000755000000000000000000000036513615410400021413 0ustar00#!/usr/bin/env cwl-runner cwlVersion: v1.0 class: CommandLineTool $namespaces: cwltool: http://commonwl.org/cwltool# requirements: cwltool:Secrets: secrets: [pw] inputs: pw: string outputs: out: stdout arguments: [cat, example.conf] cwl_utils-0.41/cwl_utils/testdata/extensions/secrets_v1_1.cwl0000755000000000000000000000036513615410400021414 0ustar00#!/usr/bin/env cwl-runner cwlVersion: v1.1 class: CommandLineTool $namespaces: cwltool: http://commonwl.org/cwltool# requirements: cwltool:Secrets: secrets: [pw] inputs: pw: string outputs: out: stdout arguments: [cat, example.conf] cwl_utils-0.41/cwl_utils/testdata/extensions/secrets_v1_2.cwl0000755000000000000000000000036513615410400021415 0ustar00#!/usr/bin/env cwl-runner cwlVersion: v1.2 class: CommandLineTool $namespaces: cwltool: http://commonwl.org/cwltool# requirements: cwltool:Secrets: secrets: [pw] inputs: pw: string outputs: out: stdout arguments: [cat, example.conf] cwl_utils-0.41/cwl_utils/testdata/extensions/shm-size_v1_0.cwl0000755000000000000000000000043413615410400021477 0ustar00#!/usr/bin/env cwl-runner class: CommandLineTool cwlVersion: v1.0 $namespaces: cwltool: "http://commonwl.org/cwltool#" requirements: cwltool:ShmSize: shmSize: 128m inputs: [] outputs: output: type: stdout baseCommand: echo stdout: shm-size.txt arguments: [ $(runtime) ] cwl_utils-0.41/cwl_utils/testdata/extensions/shm-size_v1_1.cwl0000755000000000000000000000043413615410400021500 0ustar00#!/usr/bin/env cwl-runner class: CommandLineTool cwlVersion: v1.1 $namespaces: cwltool: "http://commonwl.org/cwltool#" requirements: cwltool:ShmSize: shmSize: 128m inputs: [] outputs: output: type: stdout baseCommand: echo stdout: shm-size.txt arguments: [ $(runtime) ] cwl_utils-0.41/cwl_utils/testdata/extensions/shm-size_v1_2.cwl0000755000000000000000000000043413615410400021501 0ustar00#!/usr/bin/env cwl-runner class: CommandLineTool cwlVersion: v1.2 $namespaces: cwltool: "http://commonwl.org/cwltool#" requirements: cwltool:ShmSize: shmSize: 128m inputs: [] outputs: output: type: stdout baseCommand: echo stdout: shm-size.txt arguments: [ $(runtime) ] cwl_utils-0.41/cwl_utils/testdata/extensions/single-var-loop_v1_2.cwl0000755000000000000000000000111613615410400022756 0ustar00#!/usr/bin/env cwl-runner cwlVersion: v1.2 class: Workflow $namespaces: cwltool: "http://commonwl.org/cwltool#" requirements: InlineJavascriptRequirement: {} inputs: i1: int outputs: o1: type: int outputSource: subworkflow/o1 steps: subworkflow: run: class: ExpressionTool inputs: i1: int outputs: o1: int expression: > ${return {'o1': inputs.i1 + 1};} in: i1: i1 out: [o1] requirements: cwltool:Loop: loopWhen: $(inputs.i1 < 10) loop: i1: o1 outputMethod: last cwl_utils-0.41/cwl_utils/testdata/extensions/time-limit_v1_0.cwl0000755000000000000000000000042413615410400022011 0ustar00#!/usr/bin/env cwl-runner class: CommandLineTool cwlVersion: v1.0 $namespaces: cwltool: "http://commonwl.org/cwltool#" inputs: sleep_time: type: int default: 3 inputBinding: {} outputs: [] requirements: cwltool:TimeLimit: timelimit: 20 baseCommand: sleepcwl_utils-0.41/cwl_utils/testdata/extensions/work-reuse_v1_0.cwl0000755000000000000000000000051313615410400022041 0ustar00#!/usr/bin/env cwl-runner class: CommandLineTool cwlVersion: v1.0 $namespaces: cwltool: "http://commonwl.org/cwltool#" requirements: cwltool:WorkReuse: enableReuse: false inputs: [] outputs: page: stdout stdout: time.txt baseCommand: python arguments: - "-c" - valueFrom: | import time print(time.time()) cwl_utils-0.41/cwl_utils/testdata/remote-cwl/tool1.cwl0000755000000000000000000000107013615410400020025 0ustar00#!/usr/bin/env cwl-runner # We have this tool to test both local and remote packing class: CommandLineTool cwlVersion: v1.2 inputs: in1: type: string inputBinding: position: 1 valueFrom: A_$(inputs.in1)_B_${return inputs.in1}_C_$(inputs.in1) baseCommand: echo arguments: - valueFrom: $(runtime) outputs: out1: type: string outputBinding: glob: out.txt loadContents: true outputEval: $(self)_D_$(runtime) stdout: out.txt requirements: InlineJavascriptRequirement: expressionLib: - $include: ../lib.js cwl_utils-0.41/cwl_utils/testdata/remote-cwl/tool2.cwl0000755000000000000000000000112513615410400020027 0ustar00#!/usr/bin/env cwl-runner # We have this tool to test both local and remote packing class: CommandLineTool cwlVersion: v1.2 inputs: in1: type: ../types/testtypes.yml#my_boolean_array inputBinding: position: 1 valueFrom: A_$(inputs.in1)_B_${return inputs.in1}_C_$(inputs.in1) baseCommand: echo arguments: - valueFrom: $(runtime) outputs: out1: type: string outputBinding: glob: out.txt loadContents: true outputEval: $(self)_D_$(runtime) stdout: out.txt requirements: SchemaDefRequirement: types: - $import: ../types/testtypes.yml cwl_utils-0.41/cwl_utils/testdata/remote-cwl/wf1-input.yaml0000644000000000000000000000001513615410400020771 0ustar00in1: - true cwl_utils-0.41/cwl_utils/testdata/remote-cwl/wf1-packed.cwl0000644000000000000000000001174713615410400020722 0ustar00{ "$graph": [ { "class": "CommandLineTool", "inputs": [ { "type": "string", "inputBinding": { "position": 1, "valueFrom": "A_$(inputs.in1)_B_$(inputs.in1)_C_$(inputs.in1)" }, "id": "#tool1.cwl/in1" } ], "baseCommand": "echo", "arguments": [ { "valueFrom": "$(runtime)" } ], "stdout": "out.txt", "requirements": [ { "expressionLib": [ "var foo = function(x) {\n return 2 * x\n}\n\nvar bar = function(n, x) {\n return `{n} engineers walk into a {x}`\n}" ], "class": "InlineJavascriptRequirement" } ], "id": "#tool1.cwl", "outputs": [ { "type": "string", "outputBinding": { "glob": "out.txt", "loadContents": true, "outputEval": "$(self)_D_$(runtime)" }, "id": "#tool1.cwl/out1" } ] }, { "class": "CommandLineTool", "inputs": [ { "type": "#testtypes.yml/my_boolean_array", "inputBinding": { "position": 1, "valueFrom": "A_$(inputs.in1)_B_$(inputs.in1)_C_$(inputs.in1)" }, "id": "#tool2.cwl/in1" } ], "baseCommand": "echo", "arguments": [ { "valueFrom": "$(runtime)" } ], "outputs": [ { "type": "string", "outputBinding": { "glob": "out.txt", "loadContents": true, "outputEval": "$(self)_D_$(runtime)" }, "id": "#tool2.cwl/out1" } ], "stdout": "out.txt", "requirements": [ { "types": [ { "name": "#testtypes.yml/my_boolean_array", "type": "array", "items": "boolean", "label": "A boolean array" }, { "name": "#testtypes.yml/my_enum", "type": "enum", "symbols": [ "#testtypes.yml/my_enum/a", "#testtypes.yml/my_enum/b", "#testtypes.yml/my_enum/c" ], "label": "A required enum" } ], "class": "SchemaDefRequirement" } ], "id": "#tool2.cwl" }, { "class": "Workflow", "inputs": [ { "id": "#main/in1", "type": "#testtypes.yml/my_boolean_array" } ], "steps": [ { "run": "#tool2.cwl", "in": [ { "source": "#main/in1", "id": "#main/s1/in1" } ], "out": [ "#main/s1/out1" ], "id": "#main/s1" }, { "run": "#tool1.cwl", "in": [ { "source": "#main/s1/out1", "id": "#main/s2/in1" } ], "out": [ "#main/s2/out1" ], "id": "#main/s2" } ], "outputs": [ { "id": "#main/out1", "type": "string", "outputSource": "#main/s2/out1" } ], "requirements": [ { "types": [ { "$import": "#testtypes.yml/my_boolean_array" }, { "$import": "#testtypes.yml/my_enum" } ], "class": "SchemaDefRequirement" } ], "id": "#main" } ], "cwlVersion": "v1.2" } cwl_utils-0.41/cwl_utils/testdata/remote-cwl/wf1.cwl0000755000000000000000000000072513615410400017472 0ustar00#!/usr/bin/env cwl-runner class: Workflow cwlVersion: v1.2 inputs: - id: in1 type: ../types/testtypes.yml#my_boolean_array steps: s1: run: ./tool2.cwl in: in1: "#in1" # This should be normalized out out: [out1] s2: run: tool1.cwl in: in1: s1/out1 out: [out1] outputs: - id: out1 type: string outputSource: "#s2/out1" requirements: SchemaDefRequirement: types: - $import: ../types/testtypes.yml cwl_utils-0.41/cwl_utils/testdata/types/array.yml0000644000000000000000000000144513615410400017212 0ustar00# Contains arrays and intra-file type reference # class: SchemaDefRequirement # types: ... # This form does not work with cwltool, even though it can be found here # https://github.com/NCI-GDC/gdc-dnaseq-cwl/blob/master/tools/readgroup_path.yml # Notably, that .yml file is never used, so likely they tried it, failed and # forgot to take it out - name: sample_meta2 #duplicate names are not fine across files type: record fields: - name: prop type: string - name: study_meta type: array items: sample_meta2 # Apparently can't declare an array inside an array? # - name: study_meta_too # type: array # items: [string, sample_meta2, study_meta] - name: study_meta_too type: record fields: meta1: sample_meta2 meta2: study_meta cwl_utils-0.41/cwl_utils/testdata/types/recursive.yml0000644000000000000000000000073513615410400020104 0ustar00# Contains records and intra-file type reference # You can't have an enum in a user type - name: sample_meta type: record fields: - name: sample type: ["null", string] - name: species type: string - name: file_with_sample_meta type: record fields: - name: file type: File - name: meta type: sample_meta - name: info_with_sample_meta type: record fields: comment: type: string meta: type: sample_meta cwl_utils-0.41/cwl_utils/testdata/types/singletype.yml0000644000000000000000000000021713615410400020253 0ustar00# You can not use the dictionary format shown in # singletype2.yml. It has to be this name: simple_record type: record fields: prop: string cwl_utils-0.41/cwl_utils/testdata/types/singletype2.yml0000644000000000000000000000014413615410400020334 0ustar00# You can not use this dictionary format simple_record2: type: record fields: prop: string cwl_utils-0.41/cwl_utils/testdata/types/testtypes.yml0000644000000000000000000000024113615410400020131 0ustar00- name: my_boolean_array type: array items: boolean label: "A boolean array" - name: my_enum type: enum symbols: [a, b, c] label: "A required enum" cwl_utils-0.41/cwl_utils/testdata/workflows/clt1.cwl0000644000000000000000000000171213615410400017611 0ustar00#!/usr/bin/env cwl-runner class: CommandLineTool cwlVersion: v1.0 requirements: InitialWorkDirRequirement: listing: - entryname: inputs.txt entry: | $(inputs.in1.file.path) $(inputs.in1.meta.species) SchemaDefRequirement: types: - $import: ../types/recursive.yml - $import: ../types/array.yml - $import: ../types/singletype.yml # - $import: ../types/singletype2.yml inputs: in1: ../types/recursive.yml#file_with_sample_meta in2: type: ../types/array.yml#study_meta_too in3: type: ../types/singletype.yml#simple_record # in4: # type: ../types/singletype2.yml#simple_record2 in4: type: [string, ../types/recursive.yml#sample_meta] in5: type: Any? outputs: out1: type: File outputBinding: glob: '*.txt' out2: type: ../types/array.yml#study_meta_too outputBinding: outputEval: $(inputs.in2) out3: stdout baseCommand: [echo] arguments: [hello world] cwl_utils-0.41/cwl_utils/testdata/workflows/count-lines16-wf.cwl0000755000000000000000000000152613615410400021775 0ustar00#!/usr/bin/env cwl-runner class: Workflow cwlVersion: v1.2 inputs: file1: File outputs: count_output: {type: int, outputSource: step1/count_output} requirements: SubworkflowFeatureRequirement: {} steps: step1: in: {file1: file1} out: [count_output] run: class: Workflow inputs: file1: File outputs: count_output: {type: int, outputSource: step2/count_output} steps: step1: {run: wc-tool.cwl, in: {file1: file1}, out: [output]} step2: in: {file1: step1/output} out: [count_output] run: class: Workflow inputs: file1: File outputs: count_output: {type: int, outputSource: step1/output} steps: step1: {run: parseInt-tool.cwl, in: {file1: file1}, out: [output]} cwl_utils-0.41/cwl_utils/testdata/workflows/import-in-type.cwl0000755000000000000000000000040413615410400021643 0ustar00#!/usr/bin/env cwl-runner class: CommandLineTool cwlVersion: v1.2 inputs: file1: type: $import: type-import.yaml outputs: output: type: File outputBinding: { glob: output } baseCommand: [wc, -l] stdin: $(inputs.file1.path) stdout: output cwl_utils-0.41/cwl_utils/testdata/workflows/link-to-clt1.cwl0000755000000000000000000000000013615410400022526 2clt1.cwlustar00cwl_utils-0.41/cwl_utils/testdata/workflows/parseInt-tool.cwl0000755000000000000000000000040513615410400021507 0ustar00#!/usr/bin/env cwl-runner class: ExpressionTool requirements: - class: InlineJavascriptRequirement cwlVersion: v1.2 inputs: file1: type: File loadContents: true outputs: output: int expression: "$({'output': parseInt(inputs.file1.contents)})" cwl_utils-0.41/cwl_utils/testdata/workflows/scatter-wf4.cwl0000755000000000000000000000154513615410400021120 0ustar00#!/usr/bin/env cwl-runner cwlVersion: v1.2 $graph: - id: echo class: CommandLineTool inputs: echo_in1: type: string inputBinding: {} echo_in2: type: string inputBinding: {} outputs: echo_out: type: string outputBinding: glob: "step1_out" loadContents: true outputEval: $(self[0].contents) baseCommand: "echo" arguments: ["-n", "foo"] stdout: step1_out - id: main class: Workflow inputs: inp1: string[] inp2: string[] requirements: - class: ScatterFeatureRequirement steps: step1: scatter: [echo_in1, echo_in2] scatterMethod: dotproduct in: echo_in1: inp1 echo_in2: inp2 out: [echo_out] run: "#echo" outputs: - id: out outputSource: step1/echo_out type: type: array items: string cwl_utils-0.41/cwl_utils/testdata/workflows/type-import.yaml0000644000000000000000000000002313615410400021406 0ustar00- File - Directory cwl_utils-0.41/cwl_utils/testdata/workflows/wc-tool.cwl0000755000000000000000000000045613615410400020341 0ustar00#!/usr/bin/env cwl-runner class: CommandLineTool cwlVersion: v1.2 hints: DockerRequirement: dockerPull: docker.io/debian:stable-slim inputs: file1: File outputs: output: type: File outputBinding: { glob: output } baseCommand: [wc, -l] stdin: $(inputs.file1.path) stdout: output cwl_utils-0.41/cwl_utils/testdata/workflows/wf5-packed.cwl0000644000000000000000000002363513615410400020704 0ustar00{ "$graph": [ { "class": "CommandLineTool", "requirements": [ { "listing": [ { "entryname": "inputs.txt", "entry": "$(inputs.in1.file.path)\n$(inputs.in1.meta.species)\n" } ], "class": "InitialWorkDirRequirement" }, { "types": [ { "name": "#recursive.yml/sample_meta", "type": "record", "fields": [ { "name": "#recursive.yml/sample_meta/sample", "type": [ "null", "string" ] }, { "name": "#recursive.yml/sample_meta/species", "type": "string" } ] }, { "name": "#recursive.yml/file_with_sample_meta", "type": "record", "fields": [ { "name": "#recursive.yml/file_with_sample_meta/file", "type": "File" }, { "name": "#recursive.yml/file_with_sample_meta/meta", "type": "#recursive.yml/sample_meta" } ] }, { "name": "#recursive.yml/info_with_sample_meta", "type": "record", "fields": [ { "type": "string", "name": "#recursive.yml/info_with_sample_meta/comment" }, { "type": "#recursive.yml/sample_meta", "name": "#recursive.yml/info_with_sample_meta/meta" } ] }, { "name": "#array.yml/sample_meta2", "type": "record", "fields": [ { "name": "#array.yml/sample_meta2/prop", "type": "string" } ] }, { "name": "#array.yml/study_meta", "type": "array", "items": "#array.yml/sample_meta2" }, { "name": "#array.yml/study_meta_too", "type": "record", "fields": [ { "type": "#array.yml/sample_meta2", "name": "#array.yml/study_meta_too/meta1" }, { "type": "#array.yml/study_meta", "name": "#array.yml/study_meta_too/meta2" } ] }, { "name": "#singletype.yml/simple_record", "type": "record", "fields": [ { "type": "string", "name": "#singletype.yml/simple_record/prop" } ] } ], "class": "SchemaDefRequirement" } ], "inputs": [ { "type": "#recursive.yml/file_with_sample_meta", "id": "#link-to-clt1.cwl/in1" }, { "type": "#array.yml/study_meta_too", "id": "#link-to-clt1.cwl/in2" }, { "type": "#singletype.yml/simple_record", "id": "#link-to-clt1.cwl/in3" }, { "type": [ "string", "#recursive.yml/sample_meta" ], "id": "#link-to-clt1.cwl/in4" }, { "type": [ "null", "Any" ], "id": "#link-to-clt1.cwl/in5" } ], "baseCommand": [ "echo" ], "arguments": [ "hello world" ], "id": "#link-to-clt1.cwl", "stdout": "2cd5f434d33dce1a50ec686c741fba97b41d2544", "hints": [ { "class": "LoadListingRequirement", "loadListing": "deep_listing" }, { "class": "NetworkAccess", "networkAccess": true } ], "outputs": [ { "type": "File", "outputBinding": { "glob": "*.txt" }, "id": "#link-to-clt1.cwl/out1" }, { "type": "#array.yml/study_meta_too", "outputBinding": { "outputEval": "$(inputs.in2)" }, "id": "#link-to-clt1.cwl/out2" }, { "type": "File", "id": "#link-to-clt1.cwl/out3", "outputBinding": { "glob": "2cd5f434d33dce1a50ec686c741fba97b41d2544" } } ] }, { "class": "Workflow", "inputs": [ { "type": "#recursive.yml/file_with_sample_meta", "id": "#main/in1" }, { "type": "#array.yml/study_meta_too", "id": "#main/in2" }, { "type": "#singletype.yml/simple_record", "id": "#main/in3" }, { "type": [ "string", "#recursive.yml/sample_meta" ], "id": "#main/in4" } ], "steps": [ { "run": "#link-to-clt1.cwl", "in": [ { "source": "#main/in1", "id": "#main/s1/in1" }, { "source": "#main/in2", "id": "#main/s1/in2" }, { "source": "#main/in3", "id": "#main/s1/in3" }, { "source": "#main/in4", "id": "#main/s1/in4" } ], "out": [ "#main/s1/out2" ], "id": "#main/s1" } ], "outputs": [ { "id": "#main/out1", "type": "#array.yml/study_meta_too", "outputSource": "#main/s1/out2" } ], "requirements": [ { "types": [ { "$import": "#recursive.yml/sample_meta" }, { "$import": "#recursive.yml/file_with_sample_meta" }, { "$import": "#recursive.yml/info_with_sample_meta" }, { "$import": "#array.yml/sample_meta2" }, { "$import": "#array.yml/study_meta" }, { "$import": "#array.yml/study_meta_too" }, { "$import": "#singletype.yml/simple_record" }, { "name": "#main/user_type1", "type": "record", "fields": [ { "name": "#main/user_type1/prop", "type": "string" } ] } ], "class": "SchemaDefRequirement" } ], "id": "#main" } ], "cwlVersion": "v1.2" } cwl_utils-0.41/cwl_utils/testdata/workflows/wf5.cwl0000755000000000000000000000155413615410400017456 0ustar00#!/usr/bin/env cwl-runner # Checks symbolic links on github class: Workflow cwlVersion: v1.2 inputs: in1: type: ../types/recursive.yml#file_with_sample_meta in2: type: ../types/array.yml#study_meta_too in3: type: ../types/singletype.yml#simple_record in4: type: [string, ../types/recursive.yml#sample_meta] steps: s1: run: link-to-clt1.cwl in: in1: "#in1" # This should be normalized out in2: in2 in3: in3 in4: in4 out: [out2] outputs: - id: out1 type: ../types/array.yml#study_meta_too outputSource: "#s1/out2" requirements: SchemaDefRequirement: types: - $import: ../types/recursive.yml - $import: ../types/array.yml - $import: ../types/singletype.yml - name: user_type1 # For tools/clt2.cwl type: record fields: - name: prop type: string cwl_utils-0.41/cwl_utils/tests/__init__.py0000644000000000000000000000000013615410400015631 0ustar00cwl_utils-0.41/cwl_utils/tests/load_cwl_by_path.py0000644000000000000000000000124613615410400017401 0ustar00""" Example from README.md. Please synchronize all changes between the two. """ # SPDX-License-Identifier: Apache-2.0 from pathlib import Path from cwl_utils.parser import load_document_by_uri, save # File Input - This is the only thing you will need to adjust or take in as an input to your function: cwl_file = Path("../testdata/md5sum.cwl") # or a plain string works as well # Import CWL Object cwl_obj = load_document_by_uri(cwl_file) # View CWL Object print("List of object attributes:\n{}".format("\n".join(map(str, dir(cwl_obj))))) # Export CWL Object into a built-in typed object saved_obj = save(cwl_obj) print(f"Export of the loaded CWL object: {saved_obj}.") cwl_utils-0.41/cwl_utils/tests/test_cite_extract.py0000644000000000000000000000164513615410400017627 0ustar00# SPDX-License-Identifier: Apache-2.0 """Tests for cwl-cite-extract.""" import pytest from cwl_utils.cite_extract import arg_parser, run from .util import get_data def test_cite_extract_simple(capsys: pytest.CaptureFixture[str]) -> None: """Test the citation extraction, simply.""" assert run(arg_parser().parse_args([get_data("testdata/seqtk_seq.cwl")])) == 0 captured = capsys.readouterr() assert captured.out == "Package: seqtk, version: ['r93'], specs: None\n" assert captured.err == "" def test_cite_extract_workflow_no_results(capsys: pytest.CaptureFixture[str]) -> None: """Attempt to extract citations from a workflow without any SoftwareRequirements.""" assert ( run( arg_parser().parse_args([get_data("testdata/checker_wf/functional-wf.cwl")]) ) == 0 ) captured = capsys.readouterr() assert captured.out == "" assert captured.err == "" cwl_utils-0.41/cwl_utils/tests/test_docker_extract.py0000644000000000000000000000745113615410400020153 0ustar00# SPDX-License-Identifier: Apache-2.0 """Tests for cwl-docker-extract.""" from pathlib import Path import pytest from cwl_utils.docker_extract import arg_parser, run from .util import get_data, needs_docker, needs_podman, needs_singularity @pytest.mark.parametrize( ("target", "engine"), [ pytest.param("testdata/md5sum.cwl", "docker", marks=needs_docker), pytest.param("testdata/md5sum_v11.cwl", "docker", marks=needs_docker), pytest.param("testdata/md5sum.cwl", "podman", marks=needs_podman), pytest.param("testdata/md5sum_v11.cwl", "podman", marks=needs_podman), pytest.param("testdata/md5sum.cwl", "singularity", marks=needs_singularity), pytest.param("testdata/md5sum_v11.cwl", "singularity", marks=needs_singularity), ], ) def test_container_extraction(target: str, engine: str, tmp_path: Path) -> None: """Test container extraction tool.""" args = ["--dir", str(tmp_path), get_data(target), "--container-engine", engine] if engine == "singularity": args.append("--singularity") reqs = run(arg_parser().parse_args(args)) assert len(reqs) == 1 assert len(list(tmp_path.iterdir())) == 1 @pytest.mark.parametrize( ("engine"), [ pytest.param("docker", marks=needs_docker), pytest.param("podman", marks=needs_podman), pytest.param("singularity", marks=needs_singularity), ], ) def test_container_extraction_force(engine: str, tmp_path: Path) -> None: """Test force pull container extraction.""" args = [ "--dir", str(tmp_path), get_data("testdata/md5sum.cwl"), "--container-engine", engine, ] if engine == "singularity": args.append("--singularity") reqs = run(arg_parser().parse_args(args)) assert len(reqs) == 1 assert len(list(tmp_path.iterdir())) == 1 args = [ "--dir", str(tmp_path), get_data("testdata/md5sum.cwl"), "--container-engine", engine, "--force-download", ] if engine == "singularity": args.append("--singularity") reqs = run(arg_parser().parse_args(args)) assert len(reqs) == 1 assert len(list(tmp_path.iterdir())) == 1 @pytest.mark.parametrize( ("engine"), [ pytest.param("docker", marks=needs_docker), pytest.param("podman", marks=needs_podman), pytest.param("singularity", marks=needs_singularity), ], ) def test_container_extraction_no_dockerPull( engine: str, tmp_path: Path, capsys: pytest.CaptureFixture[str] ) -> None: """Test container extraction tool when dockerPull is missing.""" args = [ "--dir", str(tmp_path), get_data("testdata/debian_image_id.cwl"), "--container-engine", engine, ] if engine == "singularity": args.append("--singularity") reqs = run(arg_parser().parse_args(args)) assert len(reqs) == 1 assert len(list(tmp_path.iterdir())) == 0 captured = capsys.readouterr() assert captured.err == """Unable to save image from due to lack of 'dockerPull': class: DockerRequirement dockerImageId: 'debian:stable-slim.img' """ @pytest.mark.parametrize( ("engine"), [ pytest.param("docker", marks=needs_docker), pytest.param("podman", marks=needs_podman), pytest.param("singularity", marks=needs_singularity), ], ) def test_container_extraction_embedded_step(engine: str, tmp_path: Path) -> None: """Test container extraction tool.""" args = [ "--dir", str(tmp_path), get_data("testdata/workflows/count-lines16-wf.cwl"), "--container-engine", engine, ] if engine == "singularity": args.append("--singularity") reqs = run(arg_parser().parse_args(args)) assert len(reqs) == 1 assert len(list(tmp_path.iterdir())) == 1 cwl_utils-0.41/cwl_utils/tests/test_etools_to_clt.py0000644000000000000000000002122013615410400020011 0ustar00# SPDX-License-Identifier: Apache-2.0 """Test the CWL Expression refactoring tool.""" import shutil import sys import tarfile from collections.abc import Generator from pathlib import Path from typing import TYPE_CHECKING, cast import pytest import requests from _pytest.tmpdir import TempPathFactory from pytest import raises import cwl_utils.parser.cwl_v1_0 as parser import cwl_utils.parser.cwl_v1_1 as parser1 import cwl_utils.parser.cwl_v1_2 as parser2 from cwl_utils.cwl_v1_0_expression_refactor import traverse as traverse0 from cwl_utils.cwl_v1_1_expression_refactor import traverse as traverse1 from cwl_utils.cwl_v1_2_expression_refactor import traverse as traverse2 from cwl_utils.errors import WorkflowException from cwl_utils.expression_refactor import run as expression_refactor from .util import get_data if TYPE_CHECKING: from http.client import HTTPResponse def test_v1_0_workflow_top_level_format_expr() -> None: """Test for the correct error when converting a format expression in a workflow level input.""" with raises(WorkflowException, match=r".*format specification.*"): result, modified = traverse0( parser.load_document(get_data("testdata/workflow_input_format_expr.cwl")), False, False, False, False, ) def test_v1_0_workflow_top_level_sf_expr() -> None: """Test for the correct error when converting a secondaryFiles expression in a workflow level input.""" with raises(WorkflowException, match=r".*secondaryFiles.*"): result, modified = traverse0( parser.load_document(get_data("testdata/workflow_input_sf_expr.cwl")), False, False, False, False, ) def test_v1_0_workflow_top_level_sf_expr_array() -> None: """Test correct error when converting a secondaryFiles expression (array form) in a workflow level input.""" # noqa: B950 with raises(WorkflowException, match=r".*secondaryFiles.*"): result, modified = traverse0( parser.load_document(get_data("testdata/workflow_input_sf_expr_array.cwl")), False, False, False, False, ) def test_v1_1_workflow_top_level_format_expr() -> None: """Test for the correct error when converting a format expression in a workflow level input.""" with raises(WorkflowException, match=r".*format specification.*"): result, modified = traverse1( parser1.load_document( get_data("testdata/workflow_input_format_expr_v1_1.cwl") ), False, False, False, False, ) def test_v1_1_workflow_top_level_sf_expr() -> None: """Test for the correct error when converting a secondaryFiles expression in a workflow level input.""" with raises(WorkflowException, match=r".*secondaryFiles.*"): result, modified = traverse1( parser1.load_document(get_data("testdata/workflow_input_sf_expr_v1_1.cwl")), False, False, False, False, ) def test_v1_1_workflow_top_level_sf_expr_array() -> None: """Test for the correct error when converting a secondaryFiles expression (array form) in a workflow level input.""" # noqa: B950 with raises(WorkflowException, match=r".*secondaryFiles.*"): result, modified = traverse1( parser1.load_document( get_data("testdata/workflow_input_sf_expr_array_v1_1.cwl") ), False, False, False, False, ) def test_v1_2_workflow_top_level_format_expr() -> None: """Test for the correct error when converting a format expression in a workflow level input.""" with raises(WorkflowException, match=r".*format specification.*"): result, modified = traverse2( parser2.load_document( get_data("testdata/workflow_input_format_expr_v1_2.cwl") ), False, False, False, False, ) def test_v1_2_workflow_top_level_sf_expr() -> None: """Test for the correct error when converting a secondaryFiles expression in a workflow level input.""" with raises(WorkflowException, match=r".*secondaryFiles.*"): result, modified = traverse2( parser2.load_document(get_data("testdata/workflow_input_sf_expr_v1_2.cwl")), False, False, False, False, ) def test_v1_2_workflow_top_level_sf_expr_array() -> None: """Test for the correct error when converting a secondaryFiles expression (array form) in a workflow level input.""" # noqa: B950 with raises(WorkflowException, match=r".*secondaryFiles.*"): result, modified = traverse2( parser2.load_document( get_data("testdata/workflow_input_sf_expr_array_v1_2.cwl") ), False, False, False, False, ) def test_v1_0_step_valuefrom_expr_multisource() -> None: """Convert a valueFrom expression that has multiple sources.""" result, modified = traverse0( parser.load_document(get_data("testdata/step-valuefrom2-wf_v1_0.cwl")), False, False, False, False, ) def test_v1_1_step_valuefrom_expr_multisource() -> None: """Convert a valueFrom expression that has multiple sources.""" result, modified = traverse1( parser1.load_document(get_data("testdata/step-valuefrom2-wf_v1_1.cwl")), False, False, False, False, ) def test_v1_2_step_valuefrom_expr_multisource() -> None: """Convert a valueFrom expression that has multiple sources.""" result, modified = traverse2( parser2.load_document(get_data("testdata/step-valuefrom2-wf_v1_2.cwl")), False, False, False, False, ) def test_v1_0_step_valuefrom_expr_sibling_inputs() -> None: """Convert a valueFrom expression from a step input that has uninvolved sibling inputs.""" result, modified = traverse0( parser.load_document(get_data("testdata/step-valuefrom3-wf_v1_0.cwl")), False, False, False, False, ) def test_v1_1_step_valuefrom_expr_sibling_inputs() -> None: """Convert a valueFrom expression from a step input that has uninvolved sibling inputs.""" result, modified = traverse1( parser1.load_document(get_data("testdata/step-valuefrom3-wf_v1_1.cwl")), False, False, False, False, ) def test_v1_2_step_valuefrom_expr_sibling_inputs() -> None: """Convert a valueFrom expression from a step input that has uninvolved sibling inputs.""" result, modified = traverse2( parser2.load_document(get_data("testdata/step-valuefrom3-wf_v1_2.cwl")), False, False, False, False, ) def test_v1_2_workflow_output_pickvalue_expr() -> None: """Convert a workflow output pickValue expression.""" result, modified = traverse2( parser2.load_document(get_data("testdata/cond-wf-003.1.cwl")), False, False, False, False, ) def test_expression_refactor(tmp_path: Path) -> None: """Functional test.""" input_path = get_data("testdata/cond-wf-003.1.cwl") result = expression_refactor([str(tmp_path), input_path]) assert result == 0 def test_expression_refactor_noop_solo(tmp_path: Path) -> None: """Functional test.""" input_path = get_data("testdata/dockstore-tool-md5sum.cwl") result = expression_refactor([str(tmp_path), input_path]) assert result == 7 def test_expression_refactor_noop(tmp_path: Path) -> None: """Functional test.""" input_path1 = get_data("testdata/dockstore-tool-md5sum.cwl") input_path2 = get_data("testdata/echo-tool-packed.cwl") result = expression_refactor([str(tmp_path), input_path1, input_path2]) assert result == 0 @pytest.fixture(scope="session") def cwl_v1_0_dir( tmp_path_factory: TempPathFactory, ) -> Generator[str, None, None]: """Download the CWL 1.0.2 specs and return a path to the directory.""" tmp_path = tmp_path_factory.mktemp("cwl_v1_0_dir") with cast( "HTTPResponse", requests.get( "https://github.com/common-workflow-language/common-workflow-language/archive/v1.0.2.tar.gz", stream=True, ).raw, ) as specfileobj: tf = tarfile.open(fileobj=specfileobj) if sys.version_info > (3, 12): tf.extractall(path=tmp_path, filter="data") else: tf.extractall(path=tmp_path) yield str(tmp_path / "common-workflow-language-1.0.2") shutil.rmtree(Path(tmp_path)) cwl_utils-0.41/cwl_utils/tests/test_examples.py0000644000000000000000000000110213615410400016753 0ustar00# SPDX-License-Identifier: Apache-2.0 """Tests of example Python scripts.""" import os import runpy from importlib.resources import as_file, files from pathlib import Path def test_load_example() -> None: """Test the load_cwl_by_path.py script.""" cwd = Path.cwd() target = files("cwl_utils").joinpath("tests/load_cwl_by_path.py") with as_file(target) as target_path: os.chdir(target_path.parent) result_raw = runpy.run_path(str(target_path)) os.chdir(cwd) result = result_raw["saved_obj"] assert result["class"] == "Workflow" cwl_utils-0.41/cwl_utils/tests/test_extensions.py0000644000000000000000000002153213615410400017345 0ustar00from cwl_utils.parser import cwl_v1_0, cwl_v1_1, cwl_v1_2, load_document_by_uri from .util import get_path def test_cuda_requirement_v1_0() -> None: """Test that CUDARequirement objects are correctly loaded for CWL v1.0.""" uri = get_path("testdata/extensions/cuda-requirement_v1_0.cwl").as_uri() cwl_obj = load_document_by_uri(uri) assert isinstance(next(iter(cwl_obj.requirements)), cwl_v1_0.CUDARequirement) cwl_dict = cwl_obj.save(top=True) assert cwl_dict["requirements"][0]["class"] == "cwltool:CUDARequirement" def test_cuda_requirement_v1_1() -> None: """Test that CUDARequirement objects are correctly loaded for CWL v1.1.""" uri = get_path("testdata/extensions/cuda-requirement_v1_1.cwl").as_uri() cwl_obj = load_document_by_uri(uri) assert isinstance(next(iter(cwl_obj.requirements)), cwl_v1_1.CUDARequirement) cwl_dict = cwl_obj.save(top=True) assert cwl_dict["requirements"][0]["class"] == "cwltool:CUDARequirement" def test_cuda_requirement_v1_2() -> None: """Test that CUDARequirement objects are correctly loaded for CWL v1.2.""" uri = get_path("testdata/extensions/cuda-requirement_v1_2.cwl").as_uri() cwl_obj = load_document_by_uri(uri) assert isinstance(next(iter(cwl_obj.requirements)), cwl_v1_2.CUDARequirement) cwl_dict = cwl_obj.save(top=True) assert cwl_dict["requirements"][0]["class"] == "cwltool:CUDARequirement" def test_load_listing_requirement_v1_0() -> None: """Test that LoadListingRequirement objects are correctly loaded for CWL v1.0.""" uri = get_path("testdata/extensions/load-listing-requirement_v1_0.cwl").as_uri() cwl_obj = load_document_by_uri(uri) assert isinstance(next(iter(cwl_obj.requirements)), cwl_v1_0.LoadListingRequirement) cwl_dict = cwl_obj.save(top=True) assert cwl_dict["requirements"][0]["class"] == "cwltool:LoadListingRequirement" def test_loop_v1_2() -> None: """Test that Loop and LoopInput objects are correctly loaded for CWL v1.2.""" uri = get_path("testdata/extensions/single-var-loop_v1_2.cwl").as_uri() cwl_obj = load_document_by_uri(uri) cwl_step = next(iter(cwl_obj.steps)) loop_req = next(iter(cwl_step.requirements)) assert isinstance(loop_req, cwl_v1_2.Loop) assert isinstance(next(iter(loop_req.loop)), cwl_v1_2.LoopInput) cwl_dict = cwl_obj.save(top=True) assert cwl_dict["steps"][0]["requirements"][0]["class"] == "cwltool:Loop" def test_inplace_update_requirement_v1_0() -> None: """Test that InplaceUpdateRequirement objects are correctly loaded for CWL v1.0.""" uri = get_path("testdata/extensions/inplace-update-requirement_v1_0.cwl").as_uri() cwl_obj = load_document_by_uri(uri) assert isinstance( next(iter(cwl_obj.requirements)), cwl_v1_0.InplaceUpdateRequirement ) cwl_dict = cwl_obj.save(top=True) assert cwl_dict["requirements"][0]["class"] == "cwltool:InplaceUpdateRequirement" def test_mpi_requirement_v1_0() -> None: """Test that MPIRequirement objects are correctly loaded for CWL v1.0.""" uri = get_path("testdata/extensions/mpi-requirement_v1_0.cwl").as_uri() cwl_obj = load_document_by_uri(uri) assert isinstance(next(iter(cwl_obj.requirements)), cwl_v1_0.MPIRequirement) cwl_dict = cwl_obj.save(top=True) assert cwl_dict["requirements"][0]["class"] == "cwltool:MPIRequirement" def test_mpi_requirement_v1_1() -> None: """Test that MPIRequirement objects are correctly loaded for CWL v1.1.""" uri = get_path("testdata/extensions/mpi-requirement_v1_1.cwl").as_uri() cwl_obj = load_document_by_uri(uri) assert isinstance(next(iter(cwl_obj.requirements)), cwl_v1_1.MPIRequirement) cwl_dict = cwl_obj.save(top=True) assert cwl_dict["requirements"][0]["class"] == "cwltool:MPIRequirement" def test_mpi_requirement_v1_2() -> None: """Test that MPIRequirement objects are correctly loaded for CWL v1.2.""" uri = get_path("testdata/extensions/mpi-requirement_v1_2.cwl").as_uri() cwl_obj = load_document_by_uri(uri) assert isinstance(next(iter(cwl_obj.requirements)), cwl_v1_2.MPIRequirement) cwl_dict = cwl_obj.save(top=True) assert cwl_dict["requirements"][0]["class"] == "cwltool:MPIRequirement" def test_network_access_v1_0() -> None: """Test that NetworkAccess objects are correctly loaded for CWL v1.0.""" uri = get_path("testdata/extensions/network-access_v1_0.cwl").as_uri() cwl_obj = load_document_by_uri(uri) assert isinstance(next(iter(cwl_obj.requirements)), cwl_v1_0.NetworkAccess) cwl_dict = cwl_obj.save(top=True) assert cwl_dict["requirements"][0]["class"] == "cwltool:NetworkAccess" def test_process_generator_v1_0() -> None: """Test that ProcessGenerator objects are correctly loaded for CWL v1.0.""" uri = get_path("testdata/extensions/process-generator_v1_0.cwl").as_uri() cwl_obj = load_document_by_uri(uri) assert isinstance(cwl_obj, cwl_v1_0.ProcessGenerator) cwl_dict = cwl_obj.save(top=True) assert cwl_dict["class"] == "cwltool:ProcessGenerator" def test_process_generator_v1_1() -> None: """Test that ProcessGenerator objects are correctly loaded for CWL v1.1.""" uri = get_path("testdata/extensions/process-generator_v1_1.cwl").as_uri() cwl_obj = load_document_by_uri(uri) assert isinstance(cwl_obj, cwl_v1_1.ProcessGenerator) cwl_dict = cwl_obj.save(top=True) assert cwl_dict["class"] == "cwltool:ProcessGenerator" def test_process_generator_v1_2() -> None: """Test that ProcessGenerator objects are correctly loaded for CWL v1.2.""" uri = get_path("testdata/extensions/process-generator_v1_2.cwl").as_uri() cwl_obj = load_document_by_uri(uri) assert isinstance(cwl_obj, cwl_v1_2.ProcessGenerator) cwl_dict = cwl_obj.save(top=True) assert cwl_dict["class"] == "cwltool:ProcessGenerator" def test_secrets_v1_0() -> None: """Test that Secrets objects are correctly loaded for CWL v1.0.""" uri = get_path("testdata/extensions/secrets_v1_0.cwl").as_uri() cwl_obj = load_document_by_uri(uri) assert isinstance(next(iter(cwl_obj.requirements)), cwl_v1_0.Secrets) cwl_dict = cwl_obj.save(top=True) assert cwl_dict["requirements"][0]["class"] == "cwltool:Secrets" def test_secrets_v1_1() -> None: """Test that Secrets objects are correctly loaded for CWL v1.1.""" uri = get_path("testdata/extensions/secrets_v1_1.cwl").as_uri() cwl_obj = load_document_by_uri(uri) assert isinstance(next(iter(cwl_obj.requirements)), cwl_v1_1.Secrets) cwl_dict = cwl_obj.save(top=True) assert cwl_dict["requirements"][0]["class"] == "cwltool:Secrets" def test_secrets_v1_2() -> None: """Test that Secrets objects are correctly loaded for CWL v1.2.""" uri = get_path("testdata/extensions/secrets_v1_2.cwl").as_uri() cwl_obj = load_document_by_uri(uri) assert isinstance(next(iter(cwl_obj.requirements)), cwl_v1_2.Secrets) cwl_dict = cwl_obj.save(top=True) assert cwl_dict["requirements"][0]["class"] == "cwltool:Secrets" def test_shm_size_v1_0() -> None: """Test that ShmSize objects are correctly loaded for CWL v1.0.""" uri = get_path("testdata/extensions/shm-size_v1_0.cwl").as_uri() cwl_obj = load_document_by_uri(uri) assert isinstance(next(iter(cwl_obj.requirements)), cwl_v1_0.ShmSize) cwl_dict = cwl_obj.save(top=True) assert cwl_dict["requirements"][0]["class"] == "cwltool:ShmSize" def test_shm_size_v1_1() -> None: """Test that ShmSize objects are correctly loaded for CWL v1.1.""" uri = get_path("testdata/extensions/shm-size_v1_1.cwl").as_uri() cwl_obj = load_document_by_uri(uri) assert isinstance(next(iter(cwl_obj.requirements)), cwl_v1_1.ShmSize) cwl_dict = cwl_obj.save(top=True) assert cwl_dict["requirements"][0]["class"] == "cwltool:ShmSize" def test_shm_size_v1_2() -> None: """Test that ShmSize objects are correctly loaded for CWL v1.2.""" uri = get_path("testdata/extensions/shm-size_v1_2.cwl").as_uri() cwl_obj = load_document_by_uri(uri) assert isinstance(next(iter(cwl_obj.requirements)), cwl_v1_2.ShmSize) cwl_dict = cwl_obj.save(top=True) assert cwl_dict["requirements"][0]["class"] == "cwltool:ShmSize" def test_time_limit_v1_0() -> None: """Test that TimeLimit objects are correctly loaded for CWL v1.0.""" uri = get_path("testdata/extensions/time-limit_v1_0.cwl").as_uri() cwl_obj = load_document_by_uri(uri) assert isinstance(next(iter(cwl_obj.requirements)), cwl_v1_0.TimeLimit) cwl_dict = cwl_obj.save(top=True) assert cwl_dict["requirements"][0]["class"] == "cwltool:TimeLimit" def test_work_reuse_v1_0() -> None: """Test that WorkReuse objects are correctly loaded for CWL v1.0.""" uri = get_path("testdata/extensions/work-reuse_v1_0.cwl").as_uri() cwl_obj = load_document_by_uri(uri) assert isinstance(next(iter(cwl_obj.requirements)), cwl_v1_0.WorkReuse) cwl_dict = cwl_obj.save(top=True) assert cwl_dict["requirements"][0]["class"] == "cwltool:WorkReuse" cwl_utils-0.41/cwl_utils/tests/test_format.py0000644000000000000000000001502413615410400016435 0ustar00# SPDX-License-Identifier: Apache-2.0 """Tests of cwl_utils.file_formats.""" import xml.sax from pathlib import Path import requests from pytest import raises from rdflib import Graph from rdflib.compare import to_isomorphic from rdflib.plugins.parsers.notation3 import BadSyntax from schema_salad.exceptions import ValidationException from schema_salad.fetcher import DefaultFetcher from cwl_utils.file_formats import check_format from cwl_utils.parser import load_document_by_uri from cwl_utils.types import CWLFileType from .util import get_path def _create_file(format_: str | None = None) -> CWLFileType: obj = CWLFileType( **{ "class": "File", "basename": "example.txt", "size": 23, "contents": "hoopla", "nameroot": "example", "nameext": "txt", } ) if format_: obj["format"] = format_ return obj def _load_format(fetchpath: Path) -> Graph: fetcher = DefaultFetcher({}, requests.Session()) fetchurl = fetchpath.as_uri() content = fetcher.fetch_text(fetchurl) graph = Graph() for fmt in ("xml", "turtle", "rdfa"): try: graph.parse(data=content, format=fmt, publicID=fetchurl) break except (xml.sax.SAXParseException, TypeError, BadSyntax): pass return graph EDAM = _load_format(get_path("testdata/EDAM_subset.owl")) GX = _load_format(get_path("testdata/gx_edam.ttl")) def test_check_format() -> None: """Exact format equivalence test, with ontology.""" check_format( actual_file=_create_file(format_="http://edamontology.org/format_2330"), input_formats="http://edamontology.org/format_2330", ontology=EDAM, ) def test_check_format_subformat() -> None: """Test of check_format with a subformat.""" check_format( actual_file=_create_file(format_="http://edamontology.org/format_1929"), input_formats="http://edamontology.org/format_2330", ontology=EDAM, ) def test_check_format_equiv() -> None: """Test of check_format with an equivalent format.""" check_format( actual_file=_create_file(format_="http://edamontology.org/format_1929"), input_formats="http://galaxyproject.org/formats/fasta", ontology=EDAM + GX, ) def test_check_format_equiv2() -> None: """Test of check_format with an equivalent format, in the reverse.""" check_format( actual_file=_create_file(format_="http://galaxyproject.org/formats/fasta"), input_formats="http://edamontology.org/format_1929", ontology=EDAM + GX, ) def test_check_format_wrong_format() -> None: """Test of check_format with a non-match format with an ontology.""" with raises(ValidationException, match=r"File has an incompatible format: .*"): check_format( actual_file=_create_file(format_="http://edamontology.org/format_1929"), input_formats="http://edamontology.org/format_2334", ontology=EDAM, ) def test_check_format_wrong_format_no_ontology() -> None: """Test of check_format with a non-match format.""" with raises(ValidationException, match=r"File has an incompatible format: .*"): check_format( actual_file=_create_file(format_="http://edamontology.org/format_1929"), input_formats="http://edamontology.org/format_2334", ontology=None, ) def test_check_format_no_format() -> None: """Confirm that a missing format produces the expected exception.""" with raises(ValidationException, match=r"File has no 'format' defined: .*"): check_format( actual_file=_create_file(), input_formats="http://edamontology.org/format_2330", ontology=EDAM, ) def test_check_format_missing_file() -> None: """Confirm that a missing file produces no error.""" check_format( actual_file=[], input_formats="http://edamontology.org/format_2330", ontology=EDAM, ) def test_check_format_no_ontology() -> None: """Confirm that precisely matching formats without an ontology still match.""" check_format( actual_file=_create_file(format_="http://edamontology.org/format_2330"), input_formats="http://edamontology.org/format_2330", ontology=Graph(), ) def test_loading_options_graph_property_v1_0() -> None: """Test that RDFLib Graph representations of $schema properties are correctly loaded, CWL v1.0.""" uri = get_path("testdata/formattest2_v1_0.cwl").as_uri() cwl_obj = load_document_by_uri(uri) assert to_isomorphic(cwl_obj.loadingOptions.graph) == to_isomorphic(EDAM) def test_loading_options_graph_property_v1_1() -> None: """Test that RDFLib Graph representations of $schema properties are correctly loaded, CWL v1.1.""" uri = get_path("testdata/formattest2_v1_1.cwl").as_uri() cwl_obj = load_document_by_uri(uri) assert to_isomorphic(cwl_obj.loadingOptions.graph) == to_isomorphic(EDAM) def test_loading_options_graph_property_v1_2() -> None: """Test that RDFLib Graph representations of $schema properties are correctly loaded, CWL v1.2.""" uri = get_path("testdata/formattest2.cwl").as_uri() cwl_obj = load_document_by_uri(uri) assert to_isomorphic(cwl_obj.loadingOptions.graph) == to_isomorphic(EDAM) def test_loading_options_missing_graph_v1_0() -> None: """Affirm that v1.0 documents without $schema still produce an empty graph property.""" uri = get_path("testdata/workflow_input_format_expr.cwl").as_uri() cwl_obj = load_document_by_uri(uri) assert to_isomorphic(cwl_obj.loadingOptions.graph) == to_isomorphic(Graph()) def test_loading_options_missing_graph_v1_1() -> None: """Affirm that v1.1 documents without $schema still produce an empty graph property.""" uri = get_path("testdata/workflow_input_format_expr_v1_1.cwl").as_uri() cwl_obj = load_document_by_uri(uri) assert to_isomorphic(cwl_obj.loadingOptions.graph) == to_isomorphic(Graph()) def test_loading_options_missing_graph_v1_2() -> None: """Affirm that v1.2 documents without $schema still produce an empty graph property.""" uri = get_path("testdata/workflow_input_format_expr_v1_2.cwl").as_uri() cwl_obj = load_document_by_uri(uri) assert to_isomorphic(cwl_obj.loadingOptions.graph) == to_isomorphic(Graph()) def test_loading_format_without_schema_v1_0() -> None: """Test that format fields without accompanying schemas are tolerated, CWL v1.0.""" uri = get_path("testdata/revsort-run-1-packed.cwl").as_uri() load_document_by_uri(uri) cwl_utils-0.41/cwl_utils/tests/test_graph_split.py0000644000000000000000000000537313615410400017467 0ustar00# SPDX-License-Identifier: Apache-2.0 """Test the CWL $graph document splitter tool.""" import json from io import StringIO from pathlib import Path import pytest import requests from cwl_utils.graph_split import graph_split from .util import get_path URI = ( "https://gist.githubusercontent.com/altairwei/" "6a0097db95cad23de36f825ed3b9f4b0/raw/" "83f332931c3093ee73554cd7f60054ce17d03239/rhapsody_wta_1.8.packed.cwl" ) def test_graph_split(tmp_path: Path) -> None: """Confirm that a user provided example produces no exception.""" sourceIO = StringIO(requests.get(URI).text) sourceIO.name = URI graph_split(sourceIO, tmp_path, "yaml", "main.cwl", True) def test_graph_split_offline(tmp_path: Path) -> None: """Confirm that a local provided example produces no exception.""" from cwltool.tests.util import get_main_output with get_path("testdata/js-expr-req-wf.cwl").open() as handle: graph_split(handle, tmp_path, "yaml", "main.cwl", True) target = tmp_path / "wf.cwl" assert target.exists() code, stdout, stderr = get_main_output(["--debug", str(target)]) assert code == 0, stderr assert ( json.loads(stdout)["out"]["checksum"] == "sha1$7448d8798a4380162d4b56f9b452e2f6f9e24e7a" ) def test_graph_split_json_offline(tmp_path: Path) -> None: """Confirm that a local provided example produces no exception in JSON mode.""" from cwltool.tests.util import get_main_output target = tmp_path / "subdir" / "wf.cwl" with get_path("testdata/js-expr-req-wf.cwl").open() as handle: graph_split(handle, target.parent, "json", "main.cwl", True) assert target.exists() code, stdout, stderr = get_main_output(["--debug", str(target)]) assert code == 0, stderr assert ( json.loads(stdout)["out"]["checksum"] == "sha1$7448d8798a4380162d4b56f9b452e2f6f9e24e7a" ) def test_graph_split_bad_path() -> None: """Expect an exception when the target directory parent does not exist.""" with get_path("testdata/js-expr-req-wf.cwl").open() as handle: with pytest.raises(NotADirectoryError): graph_split( handle, Path("/__non_existent/tmp_path"), "json", "main.cwl", True ) def test_graph_split_complex1(tmp_path: Path) -> None: """Split a more complex graph with SchemaDefRequirement and $import.""" with get_path("testdata/remote-cwl/wf1-packed.cwl").open() as handle: graph_split(handle, tmp_path, "yaml", "main.cwl", False) def test_graph_split_complex2(tmp_path: Path) -> None: """Split another complex graph with SchemaDefRequirement and $import.""" with get_path("testdata/workflows/wf5-packed.cwl").open() as handle: graph_split(handle, tmp_path, "yaml", "main.cwl", False) cwl_utils-0.41/cwl_utils/tests/test_inputs_schema_gen.py0000644000000000000000000000541413615410400020642 0ustar00# SPDX-License-Identifier: Apache-2.0 """Tests for cwl-inputs-schema-gen.""" from pathlib import Path import pytest from jsonschema.exceptions import SchemaError, ValidationError from jsonschema.validators import validate from ruamel.yaml import YAML from cwl_utils.inputs_schema_gen import cwl_to_jsonschema from cwl_utils.loghandler import _logger as _cwlutilslogger from cwl_utils.parser import load_document_by_uri from .util import get_path TEST_PARAMS = [ # Packed Case ( get_path("testdata/revsort-packed.cwl"), get_path("testdata/revsort-job.json"), ), # The number of parameters is a little large, and the definition itself is a straightforward case. ( get_path("testdata/bwa-mem-tool.cwl"), get_path("testdata/bwa-mem-job.json"), ), # The case where CommandInputParameter is shortened (e.g., param: string) ( get_path("testdata/env-tool1.cwl"), get_path("testdata/env-job.json"), ), # Dir ( get_path("testdata/dir.cwl"), get_path("testdata/dir-job.yml"), ), # SecondaryFiles ( get_path("testdata/rename-inputs.cwl"), get_path("testdata/rename-inputs.yml"), ), # Stage array ( get_path("testdata/stage-array.cwl"), get_path("testdata/stage-array-job.json"), ), ] @pytest.mark.parametrize("tool_path,inputs_path", TEST_PARAMS) def test_cwl_inputs_to_jsonschema(tool_path: Path, inputs_path: Path) -> None: cwl_obj = load_document_by_uri(tool_path.as_uri()) _cwlutilslogger.info(f"Generating schema for {tool_path.name}") json_schema = cwl_to_jsonschema(cwl_obj) _cwlutilslogger.info( f"Testing {inputs_path.name} against schema generated for input {tool_path.name}" ) input_obj = YAML().load(inputs_path) try: validate(input_obj, json_schema) except (ValidationError, SchemaError) as err: _cwlutilslogger.error( f"Validation failed for {inputs_path.name} " f"against schema generated for input {tool_path.name}" ) raise SchemaError(f"{inputs_path.name} failed schema validation") from err def test_cwl_inputs_to_jsonschema_fails() -> None: """Compare tool schema of param 1 against input schema of param 2.""" tool_path: Path = TEST_PARAMS[0][0] inputs_path: Path = TEST_PARAMS[3][1] cwl_obj = load_document_by_uri(tool_path.as_uri()) _cwlutilslogger.info(f"Generating schema for {tool_path.name}") json_schema = cwl_to_jsonschema(cwl_obj) _cwlutilslogger.info( f"Testing {inputs_path.name} against schema generated for input {tool_path.name}" ) input_obj = YAML().load(inputs_path) # We expect this to fail with pytest.raises(ValidationError): validate(input_obj, json_schema) cwl_utils-0.41/cwl_utils/tests/test_js_sandbox.py0000644000000000000000000001401113615410400017272 0ustar00"""Test sandboxjs.py and related code.""" import os import shutil import threading from pathlib import Path from typing import Any import pytest from cwl_utils import expression, sandboxjs from .util import needs_podman, needs_singularity, needs_udocker node_versions = [ ("v0.8.26\n", False), ("v0.10.25\n", False), ("v0.10.26\n", True), ("v4.4.2\n", True), ("v7.7.3\n", True), ] @pytest.mark.parametrize("version,supported", node_versions) def test_node_version(version: str, supported: bool, mocker: Any) -> None: mocked_subprocess = mocker.patch("cwl_utils.sandboxjs.subprocess") mocked_subprocess.check_output = mocker.Mock(return_value=version) assert sandboxjs.check_js_threshold_version("node") == supported def test_value_from_two_concatenated_expressions() -> None: js_engine = sandboxjs.get_js_engine() js_engine.have_node_slim = False # type: ignore[attr-defined] js_engine.localdata = threading.local() # type: ignore[attr-defined] assert ( expression.do_eval( '$("a ")$("string")', {}, [{"class": "InlineJavascriptRequirement"}], None, None, {}, cwlVersion="v1.0", ) == "a string" ) def hide_nodejs(temp_dir: Path) -> str: """Generate a new PATH that hides node{js,}.""" paths: list[str] = os.environ.get("PATH", "").split(":") names: list[str] = [] if "/bin" in paths: bin_path = Path("/bin") if ( bin_path.is_symlink() and os.readlink(bin_path) == "usr/bin" and "/usr/bin" in paths ): paths.remove("/bin") for name in ("nodejs", "node"): path = shutil.which(name, path=":".join(paths)) if path: names.append(path) for name in names: dirname = os.path.dirname(name) if dirname in paths: paths.remove(dirname) new_dir = temp_dir / os.path.basename(dirname) new_dir.mkdir() for entry in os.listdir(dirname): if entry not in ("nodejs", "node"): os.symlink(Path(dirname, entry), new_dir / entry) paths.append(str(new_dir)) return ":".join(paths) @needs_podman def test_value_from_two_concatenated_expressions_podman( tmp_path: Path, monkeypatch: pytest.MonkeyPatch ) -> None: """Javascript test using podman.""" new_paths = hide_nodejs(tmp_path) with monkeypatch.context() as m: m.setenv("PATH", new_paths) js_engine = sandboxjs.get_js_engine() js_engine.have_node_slim = False # type: ignore[attr-defined] js_engine.localdata = threading.local() # type: ignore[attr-defined] assert ( expression.do_eval( '$("a ")$("string")', {}, [{"class": "InlineJavascriptRequirement"}], None, None, {}, cwlVersion="v1.0", container_engine="podman", ) == "a string" ) @needs_udocker def test_value_from_two_concatenated_expressions_udocker( tmp_path: Path, monkeypatch: pytest.MonkeyPatch ) -> None: """Javascript test using udocker.""" new_paths = hide_nodejs(tmp_path) with monkeypatch.context() as m: m.setenv("PATH", new_paths) js_engine = sandboxjs.get_js_engine() js_engine.have_node_slim = False # type: ignore[attr-defined] js_engine.localdata = threading.local() # type: ignore[attr-defined] assert ( expression.do_eval( '$("a ")$("string")', {}, [{"class": "InlineJavascriptRequirement"}], None, None, {}, cwlVersion="v1.0", container_engine="udocker", ) == "a string" ) @needs_singularity def test_value_from_two_concatenated_expressions_singularity( tmp_path: Path, monkeypatch: pytest.MonkeyPatch ) -> None: """Javascript test using Singularity.""" new_paths = hide_nodejs(tmp_path) with monkeypatch.context() as m: m.setenv("PATH", new_paths) js_engine = sandboxjs.get_js_engine() js_engine.have_node_slim = False # type: ignore[attr-defined] js_engine.localdata = threading.local() # type: ignore[attr-defined] assert ( expression.do_eval( '$("a ")$("string")', {}, [{"class": "InlineJavascriptRequirement"}], None, None, {}, cwlVersion="v1.0", container_engine="singularity", ) == "a string" ) @needs_singularity def test_singularity_cache(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None: """Affirm that CWL_SINGULARIT_CACHE is respected.""" bin_path = tmp_path / "no_nodejs" bin_path.mkdir() new_paths = hide_nodejs(bin_path) cache_path = tmp_path / "singularity_cache" cache_path.mkdir() with monkeypatch.context() as m: m.setenv("PATH", new_paths) m.setenv("CWL_SINGULARITY_CACHE", str(cache_path)) js_engine = sandboxjs.get_js_engine() js_engine.localdata = threading.local() # type: ignore[attr-defined] js_engine.have_node_slim = False # type: ignore[attr-defined] assert ( expression.do_eval( "$(42*23)", {}, [{"class": "InlineJavascriptRequirement"}], None, None, {}, cwlVersion="v1.0", container_engine="singularity", ) == 42 * 23 ) assert (cache_path / "node_alpine.sif").exists() def test_caches_js_processes(mocker: Any) -> None: sandboxjs.exec_js_process("7", context="{}") mocked_new_js_proc = mocker.patch("cwl_utils.sandboxjs.new_js_proc") sandboxjs.exec_js_process("7", context="{}") mocked_new_js_proc.assert_not_called() cwl_utils-0.41/cwl_utils/tests/test_meta.py0000644000000000000000000000041613615410400016072 0ustar00# SPDX-License-Identifier: Apache-2.0 """Test __meta__ properties.""" from cwl_utils.__meta__ import __version__ def test_graph_split() -> None: """Confirm that __version__ exists and is a string.""" assert __version__ assert isinstance(__version__, str) cwl_utils-0.41/cwl_utils/tests/test_packing.py0000644000000000000000000000621413615410400016562 0ustar00from typing import Any from cwl_utils.pack import pack from .util import get_data def _find(l_item: list[Any], key: str, val: str) -> Any: return next(_x for _x in l_item if _x[key] == val) def test_port_normalization() -> None: cwl = pack(get_data("testdata/remote-cwl/wf1.cwl")) step_s1 = _find(cwl.get("steps", []), "id", "s1") step_in1 = _find(step_s1.get("in"), "id", "in1") assert step_in1["source"] == "in1" cwl = pack(get_data("testdata/wf2.cwl")) step_s1 = _find(cwl.get("steps", []), "id", "s1") step_in1 = _find(step_s1.get("in"), "id", "in1") assert step_in1["source"] == "in1" out1 = _find(cwl.get("outputs", []), "id", "out1") assert out1.get("outputSource") == "s2/out1" def test_include() -> None: cwl = pack(get_data("testdata/remote-cwl/tool1.cwl")) assert "arguments" in cwl assert isinstance(cwl.get("arguments"), list) inline_js_req = _find( cwl.get("requirements", []), "class", "InlineJavascriptRequirement" ) include_js = inline_js_req.get("expressionLib") assert isinstance(include_js, list) assert "engineers walk into a" in include_js[0] def test_schema_def1() -> None: cwl = pack(get_data("testdata/remote-cwl/tool2.cwl")) _type = _find(cwl.get("inputs", []), "id", "in1").get("type") assert isinstance(_type, dict) assert _type.get("type") == "array" def test_schema_def2() -> None: cwl = pack(get_data("testdata/wf2.cwl")) _type = _find(cwl.get("inputs", []), "id", "in2").get("type") assert isinstance(_type, dict) assert _type.get("type") == "enum" def test_step_packing() -> None: cwl = pack(get_data("testdata/remote-cwl/wf1.cwl")) s1 = _find(cwl.get("steps", []), "id", "s1") tool2 = s1.get("run") _type = _find(tool2.get("inputs"), "id", "in1").get("type") assert isinstance(_type, dict) assert _type.get("type") == "array" def test_embedded_packing() -> None: pack(get_data("testdata/workflows/count-lines16-wf.cwl")) def test_remote_packing() -> None: cwl = pack( "https://raw.githubusercontent.com/kaushik-work/sbpack/master/tests/wf2.cwl" ) s1 = _find(cwl.get("steps", []), "id", "s1") wf1 = s1.get("run") assert wf1.get("class") == "Workflow" tool2 = _find(wf1.get("steps"), "id", "s1").get("run") _type = _find(tool2.get("inputs"), "id", "in1").get("type") assert isinstance(_type, dict) assert _type.get("type") == "array" def test_remote_packing_github_soft_links() -> None: cwl = pack( "https://raw.githubusercontent.com/rabix/sbpack/master/tests/workflows/wf5.cwl" ) s1 = _find(cwl.get("steps", []), "id", "s1") tool1 = s1.get("run") assert tool1.get("class") == "CommandLineTool" def test_already_packed_graph() -> None: """Workflow already packed in a $graph.""" cwl = pack(get_data("testdata/workflows/scatter-wf4.cwl")) assert "inputs" not in cwl assert "outputs" not in cwl assert "$graph" in cwl assert "requirements" not in cwl def test_import_in_type() -> None: cwl = pack(get_data("testdata/workflows/import-in-type.cwl")) assert cwl["inputs"][0]["type"] == ["File", "Directory"] cwl_utils-0.41/cwl_utils/tests/test_parser.py0000644000000000000000000001441613615410400016445 0ustar00# SPDX-License-Identifier: Apache-2.0 """Test the load and save functions for CWL.""" from pytest import raises from ruamel.yaml.main import YAML import cwl_utils.parser.latest as latest from cwl_utils.errors import GraphTargetMissingException from cwl_utils.parser import ( cwl_v1_2, cwl_version, load_document, load_document_by_uri, save, ) from .util import get_path TEST_v1_0_CWL = get_path("testdata/md5sum.cwl") TEST_v1_0_CWL_REMOTE = ( "https://raw.githubusercontent.com/" "common-workflow-language/cwl-utils/main/cwl_utils/testdata/md5sum.cwl" ) TEST_v1_2_CWL = get_path("testdata/workflow_input_format_expr_v1_2.cwl") yaml = YAML(typ="rt") yaml.preserve_quotes = True def test_cwl_version() -> None: """Test cwl_version for a CommandLineTool.""" with TEST_v1_0_CWL.open() as cwl_h: yaml_obj = yaml.load(cwl_h) ver = cwl_version(yaml_obj) assert ver == "v1.0" def test_load_document() -> None: """Test load_document for a CommandLineTool.""" with TEST_v1_0_CWL.open() as cwl_h: yaml_obj = yaml.load(cwl_h) cwl_obj = load_document(yaml_obj, TEST_v1_0_CWL.as_uri()) assert cwl_obj.cwlVersion == "v1.0" assert cwl_obj.inputs[0].id.endswith("input_file") def test_load_document_with_local_uri() -> None: """Test load_document for a CommandLineTool in a local URI.""" uri = TEST_v1_0_CWL.as_uri() assert uri.startswith("file://") cwl_obj = load_document_by_uri(uri) assert cwl_obj.cwlVersion == "v1.0" assert cwl_obj.inputs[0].id.endswith("input_file") def test_load_document_with_remote_uri() -> None: """Test load_document for a CommandLineTool in a remote URI.""" cwl_obj = load_document_by_uri(TEST_v1_0_CWL_REMOTE) assert cwl_obj.cwlVersion == "v1.0" assert cwl_obj.inputs[0].id.endswith("input_file") def test_save() -> None: """Test save for a list of Process objects with different cwlVersions.""" with TEST_v1_0_CWL.open() as cwl_h: yaml_obj10 = yaml.load(cwl_h) cwl_obj10 = load_document(yaml_obj10, TEST_v1_0_CWL.as_uri()) assert cwl_obj10.cwlVersion == "v1.0" with TEST_v1_2_CWL.open() as cwl_h: yaml_obj12 = yaml.load(cwl_h) cwl_obj12 = load_document(yaml_obj12, TEST_v1_2_CWL.as_uri()) assert cwl_obj12.cwlVersion == "v1.2" saved_obj = save([cwl_obj10, cwl_obj12]) ver = cwl_version(saved_obj) assert ver == "v1.2" def test_latest_parser() -> None: """Test the `latest` parser is same as cwl_v1_2 (current latest) parser.""" uri = TEST_v1_2_CWL.as_uri() with TEST_v1_2_CWL.open() as cwl_h: yaml_obj12 = yaml.load(cwl_h) latest_cwl_obj = latest.load_document_by_yaml(yaml_obj12, uri) assert latest_cwl_obj.cwlVersion == "v1.2" def test_shortname() -> None: assert cwl_v1_2.shortname("http://example.com/foo") == "foo" assert cwl_v1_2.shortname("http://example.com/#bar") == "bar" assert cwl_v1_2.shortname("http://example.com/foo/bar") == "bar" assert cwl_v1_2.shortname("http://example.com/foo#bar") == "bar" assert cwl_v1_2.shortname("http://example.com/#foo/bar") == "bar" assert cwl_v1_2.shortname("http://example.com/foo#bar/baz") == "baz" def test_get_id_from_graph() -> None: """Test loading an explicit id of a CWL document with $graph property.""" uri = get_path("testdata/echo-tool-packed.cwl").as_uri() cwl_obj = load_document_by_uri(uri + "#main") assert cwl_obj.id == uri + "#main" def test_get_default_id_from_graph() -> None: """Test that loading the default id of a CWL document with $graph property returns the `#main` id.""" uri = get_path("testdata/echo-tool-packed.cwl").as_uri() cwl_obj = load_document_by_uri(uri) assert cwl_obj.id == uri + "#main" def test_get_default_id_from_graph_without_main() -> None: """Test that loading the default id of a CWL document with $graph property and no `#main` id throws an error.""" # noqa: B950 uri = get_path("testdata/js-expr-req-wf.cwl").as_uri() with raises(GraphTargetMissingException): load_document_by_uri(uri) def test_graph_load_all() -> None: """Test that we can get all object in a $graph file.""" uri = get_path("testdata/js-expr-req-wf.cwl").as_uri() cwl_objs = load_document_by_uri(uri, load_all=True) assert len(cwl_objs) == 2 def test_map_ordering_v1_0() -> None: """Confirm that ID map entries are not sorted during parsing, CWL v1.0.""" uri = get_path("testdata/map-ordering-v1_0.cwl").as_uri() cwl_obj = load_document_by_uri(uri) assert cwl_obj.inputs[0].id == f"{uri}#09first_input" assert cwl_obj.inputs[1].id == f"{uri}#05second_input" assert cwl_obj.inputs[2].id == f"{uri}#01third_input" assert cwl_obj.steps[0].id == f"{uri}#zz_step_one" assert cwl_obj.steps[1].id == f"{uri}#00_step_two" assert cwl_obj.outputs[0].id == f"{uri}#zz_first_output" assert cwl_obj.outputs[1].id == f"{uri}#ll_second_output" assert cwl_obj.outputs[2].id == f"{uri}#aa_third_output" def test_map_ordering_v1_1() -> None: """Confirm that ID map entries are not sorted during parsing, CWL v1.1.""" uri = get_path("testdata/map-ordering-v1_1.cwl").as_uri() cwl_obj = load_document_by_uri(uri) assert cwl_obj.inputs[0].id == f"{uri}#09first_input" assert cwl_obj.inputs[1].id == f"{uri}#05second_input" assert cwl_obj.inputs[2].id == f"{uri}#01third_input" assert cwl_obj.steps[0].id == f"{uri}#zz_step_one" assert cwl_obj.steps[1].id == f"{uri}#00_step_two" assert cwl_obj.outputs[0].id == f"{uri}#zz_first_output" assert cwl_obj.outputs[1].id == f"{uri}#ll_second_output" assert cwl_obj.outputs[2].id == f"{uri}#aa_third_output" def test_map_ordering_v1_2() -> None: """Confirm that ID map entries are not sorted during parsing, CWL v1.2.""" uri = get_path("testdata/map-ordering-v1_2.cwl").as_uri() cwl_obj = load_document_by_uri(uri) assert cwl_obj.inputs[0].id == f"{uri}#09first_input" assert cwl_obj.inputs[1].id == f"{uri}#05second_input" assert cwl_obj.inputs[2].id == f"{uri}#01third_input" assert cwl_obj.steps[0].id == f"{uri}#zz_step_one" assert cwl_obj.steps[1].id == f"{uri}#00_step_two" assert cwl_obj.outputs[0].id == f"{uri}#zz_first_output" assert cwl_obj.outputs[1].id == f"{uri}#ll_second_output" assert cwl_obj.outputs[2].id == f"{uri}#aa_third_output" cwl_utils-0.41/cwl_utils/tests/test_parser_utils.py0000644000000000000000000014300613615410400017663 0ustar00# SPDX-License-Identifier: Apache-2.0 """Test the CWL parsers utility functions.""" import logging import re import tempfile from collections.abc import MutableSequence from typing import cast import pytest from pytest import LogCaptureFixture, raises from schema_salad.exceptions import ValidationException import cwl_utils.parser.cwl_v1_0 import cwl_utils.parser.cwl_v1_0_utils import cwl_utils.parser.cwl_v1_1 import cwl_utils.parser.cwl_v1_1_utils import cwl_utils.parser.cwl_v1_2 import cwl_utils.parser.cwl_v1_2_utils import cwl_utils.parser.utils from cwl_utils.errors import WorkflowException from cwl_utils.parser import load_document_by_uri from .util import get_path @pytest.mark.parametrize("cwlVersion", ["v1_0", "v1_1", "v1_2"]) def test_static_checker_fail(cwlVersion: str) -> None: """Confirm that static type checker raises expected exception.""" if cwlVersion == "v1_0": uri1 = get_path("testdata/checker_wf/broken-wf.cwl").as_uri() cwl_obj1 = load_document_by_uri(uri1) with pytest.raises( ValidationException, match="\nSource .* of type .* is incompatible\n.*with sink .* of type .*", ): cwl_utils.parser.utils.static_checker(cwl_obj1) uri2 = get_path("testdata/checker_wf/broken-wf2.cwl").as_uri() cwl_obj2 = load_document_by_uri(uri2) with pytest.raises(ValidationException, match="param .* not found in id: .*"): cwl_utils.parser.utils.static_checker(cwl_obj2) uri3 = get_path("testdata/checker_wf/broken-wf3.cwl").as_uri() cwl_obj3 = load_document_by_uri(uri3) with pytest.raises(ValidationException, match="param .* not found in id: .*"): cwl_utils.parser.utils.static_checker(cwl_obj3) uri4 = get_path(f"testdata/count-lines6-wf_{cwlVersion}.cwl").as_uri() cwl_obj4 = load_document_by_uri(uri4) with pytest.raises( ValidationException, match="\nSource .* of type .* is incompatible\n.*with sink .* of type .*", ): cwl_utils.parser.utils.static_checker(cwl_obj4) uri5 = get_path(f"testdata/count-lines6-single-source-wf_{cwlVersion}.cwl").as_uri() cwl_obj5 = load_document_by_uri(uri5) with pytest.raises( ValidationException, match="\nSource .* of type .* is incompatible\n.*with sink .* of type .*", ): cwl_utils.parser.utils.static_checker(cwl_obj5) if cwlVersion == "v1_2": uri6 = get_path("testdata/cond-single-source-wf-003.1.cwl").as_uri() cwl_obj6 = load_document_by_uri(uri6) with pytest.raises(ValidationException, match=".* pickValue is first_non_null"): cwl_utils.parser.utils.static_checker(cwl_obj6) uri7 = get_path("testdata/cond-single-source-wf-004.1.cwl").as_uri() cwl_obj7 = load_document_by_uri(uri7) with pytest.raises(ValidationException, match=".* pickValue is the_only_non_null"): cwl_utils.parser.utils.static_checker(cwl_obj7) def test_static_checker_warning(caplog: LogCaptureFixture) -> None: uri1 = get_path("testdata/checker_wf/warning-wf.cwl").as_uri() cwl_obj1 = load_document_by_uri(uri1) with caplog.at_level(level=logging.WARNING, logger="cwl_utils"): cwl_utils.parser.utils.static_checker(cwl_obj1) assert "Source is from conditional step and may produce `null`" in caplog.text caplog.clear() uri2 = get_path("testdata/checker_wf/no-warning-wf.cwl").as_uri() cwl_obj2 = load_document_by_uri(uri2) with caplog.at_level(level=logging.WARNING, logger="cwl_utils"): cwl_utils.parser.utils.static_checker(cwl_obj2) assert not caplog.text caplog.clear() uri3 = get_path("testdata/checker_wf/warning-wf2.cwl").as_uri() cwl_obj3 = load_document_by_uri(uri3) with caplog.at_level(level=logging.WARNING, logger="cwl_utils"): cwl_utils.parser.utils.static_checker(cwl_obj3) assert "Source is from conditional step and may produce `null`" in caplog.text caplog.clear() uri4 = get_path("testdata/checker_wf/warning-wf3.cwl").as_uri() cwl_obj4 = load_document_by_uri(uri4) with caplog.at_level(level=logging.WARNING, logger="cwl_utils"): cwl_utils.parser.utils.static_checker(cwl_obj4) assert re.search( 'with sink \'pair\' of type {"name":.* "items": "File", "type": "array"}', caplog.text, ) assert "Source is from conditional step, but pickValue is not used" in caplog.text @pytest.mark.parametrize("cwlVersion", ["v1_0", "v1_1", "v1_2"]) def test_static_checker_success(cwlVersion: str) -> None: """Confirm that static type checker correctly validates workflows.""" test_files = [ f"testdata/record-output-wf_{cwlVersion}.cwl", f"testdata/step_valuefrom5_wf_{cwlVersion}.cwl", f"testdata/step_valuefrom5_wf_with_id_{cwlVersion}.cwl", f"testdata/stdout-wf_{cwlVersion}.cwl", f"testdata/scatter-wf1_{cwlVersion}.cwl", f"testdata/scatter-wf2_{cwlVersion}.cwl", f"testdata/scatter-wf3_{cwlVersion}.cwl", f"testdata/count-lines7-wf_{cwlVersion}.cwl", f"testdata/count-lines7-single-source-wf_{cwlVersion}.cwl", ] if cwlVersion == "v1_2": test_files.extend( [ "testdata/cond-wf-003.1.cwl", "testdata/cond-wf-004.1.cwl", "testdata/cond-wf-005.1.cwl", "testdata/cond-single-source-wf-005.1.cwl", "testdata/extensions/all-output-loop_v1_2.cwl", "testdata/extensions/single-var-loop_v1_2.cwl", "testdata/wf2.cwl", ] ) for test_file in test_files: uri = get_path(test_file).as_uri() cwl_obj = load_document_by_uri(uri) cwl_utils.parser.utils.static_checker(cwl_obj) def test_v1_0_file_content_64_kB() -> None: """Test that reading file content is allowed up to 64kB in CWL v1.0.""" text = "a" * cwl_utils.parser.cwl_v1_0_utils.CONTENT_LIMIT with tempfile.TemporaryFile() as f: f.write(text.encode("utf-8")) f.seek(0) content = cwl_utils.parser.cwl_v1_0_utils.content_limit_respected_read(f) assert content == text def test_v1_0_file_content_larger_than_64_kB() -> None: """Test that reading file content is truncated to 64kB for larger files in CWL v1.0.""" text = "a" * (cwl_utils.parser.cwl_v1_0_utils.CONTENT_LIMIT + 1) with tempfile.TemporaryFile() as f: f.write(text.encode("utf-8")) f.seek(0) content = cwl_utils.parser.cwl_v1_0_utils.content_limit_respected_read(f) assert content == text[0 : cwl_utils.parser.cwl_v1_0_utils.CONTENT_LIMIT] def test_v_1_0_load_inputfile_with_format() -> None: """Test that File object with the `format` field is correctly loaded with CWL v1.0.""" doc_uri = get_path("testdata/formattest2_v1_0.cwl").as_uri() cwl_obj = load_document_by_uri(doc_uri) job_uri = get_path("testdata/formattest-job.json").as_uri() jobfile = cwl_utils.parser.utils.load_inputfile_by_uri( "v1.0", job_uri, cwl_obj.loadingOptions ) assert jobfile["input"].format == cwl_obj.inputs[0].format def test_v_1_0_load_inputfile_with_nested_array() -> None: """Test that nested arrays are preserved when loading an input file with CWL v1.0.""" job_uri = get_path("testdata/nested-array-job.yml").as_uri() jobfile = cwl_utils.parser.utils.load_inputfile_by_uri("v1.0", job_uri) assert isinstance(jobfile["letters"], MutableSequence) assert isinstance(jobfile["letters"][0], MutableSequence) assert jobfile["letters"][0][0] == "a" def test_v_1_0_load_inputfile_with_secondary_files() -> None: """Test that secondary files are treated as objects when loading an input file with CWL v1.0.""" job_uri = get_path("testdata/dir4-job.yml").as_uri() jobfile = cwl_utils.parser.utils.load_inputfile_by_uri("v1.0", job_uri) assert isinstance(jobfile["inf"].secondaryFiles[0], cwl_utils.parser.cwl_v1_0.File) assert isinstance( jobfile["inf"].secondaryFiles[1], cwl_utils.parser.cwl_v1_0.Directory ) def test_v1_0_stdout_to_file() -> None: """Test that stdout shortcut is converted to stdout parameter with CWL v1.0.""" clt = cwl_utils.parser.cwl_v1_0.CommandLineTool( inputs=[], outputs=[ cwl_utils.parser.cwl_v1_0.CommandOutputParameter(id="test", type_="stdout") ], ) cwl_utils.parser.cwl_v1_0_utils.convert_stdstreams_to_files(clt) assert clt.stdout is not None assert clt.stdout == clt.outputs[0].outputBinding.glob def test_v1_0_stdout_to_file_with_binding() -> None: """Test that outputBinding is not allowed with stdout shortcut with CWL v1.0.""" clt = cwl_utils.parser.cwl_v1_0.CommandLineTool( inputs=[], outputs=[ cwl_utils.parser.cwl_v1_0.CommandOutputParameter( id="test", type_="stdout", outputBinding=cwl_utils.parser.cwl_v1_0.CommandOutputBinding( glob="output.txt" ), ) ], ) with raises(ValidationException): cwl_utils.parser.cwl_v1_0_utils.convert_stdstreams_to_files(clt) def test_v1_0_stdout_to_file_preserve_original() -> None: """Test that stdout parameter prevails on stdout shortcut with CWL v1.0.""" clt = cwl_utils.parser.cwl_v1_0.CommandLineTool( inputs=[], outputs=[ cwl_utils.parser.cwl_v1_0.CommandOutputParameter(id="test", type_="stdout") ], stdout="original.txt", ) cwl_utils.parser.cwl_v1_0_utils.convert_stdstreams_to_files(clt) assert clt.stdout == "original.txt" assert clt.stdout == clt.outputs[0].outputBinding.glob def test_v1_0_stderr_to_file() -> None: """Test that stderr shortcut is converted to stderr parameter with CWL v1.0.""" clt = cwl_utils.parser.cwl_v1_0.CommandLineTool( inputs=[], outputs=[ cwl_utils.parser.cwl_v1_0.CommandOutputParameter(id="test", type_="stderr") ], ) cwl_utils.parser.cwl_v1_0_utils.convert_stdstreams_to_files(clt) assert clt.stderr is not None assert clt.stderr == clt.outputs[0].outputBinding.glob def test_v1_0_stderr_to_file_with_binding() -> None: """Test that outputBinding is not allowed with stderr shortcut with CWL v1.0.""" clt = cwl_utils.parser.cwl_v1_0.CommandLineTool( inputs=[], outputs=[ cwl_utils.parser.cwl_v1_0.CommandOutputParameter( id="test", type_="stderr", outputBinding=cwl_utils.parser.cwl_v1_0.CommandOutputBinding( glob="err.txt" ), ) ], ) with raises(ValidationException): cwl_utils.parser.cwl_v1_0_utils.convert_stdstreams_to_files(clt) def test_v1_0_stderr_to_file_preserve_original() -> None: """Test that stderr parameter prevails on stdout shortcut with CWL v1.0.""" clt = cwl_utils.parser.cwl_v1_0.CommandLineTool( inputs=[], outputs=[ cwl_utils.parser.cwl_v1_0.CommandOutputParameter(id="test", type_="stderr") ], stderr="original.txt", ) cwl_utils.parser.cwl_v1_0_utils.convert_stdstreams_to_files(clt) assert clt.stderr == "original.txt" assert clt.stderr == clt.outputs[0].outputBinding.glob def test_v1_0_type_compare_list() -> None: """Test that the type comparison works correctly a list type with CWL v1.0.""" uri = get_path("testdata/echo_v1_0.cwl").as_uri() cwl_obj = load_document_by_uri(uri) assert cwl_utils.parser.cwl_v1_0_utils._compare_type( cwl_obj.inputs[0].type_, cwl_obj.inputs[0].type_ ) def test_v1_0_type_compare_record() -> None: """Test that the type comparison works correctly a record type with CWL v1.0.""" uri = get_path("testdata/record-output-wf_v1_0.cwl").as_uri() cwl_obj = load_document_by_uri(uri) source_type = cwl_utils.parser.utils.type_for_source( process=cwl_obj, sourcenames=cwl_obj.outputs[0].outputSource, ) assert cwl_utils.parser.cwl_v1_0_utils._compare_type(source_type, source_type) def test_v1_0_type_for_source() -> None: """Test that the type is correctly inferred from a source id with CWL v1.0.""" uri = get_path("testdata/step_valuefrom5_wf_v1_0.cwl").as_uri() cwl_obj = load_document_by_uri(uri) source_type = cwl_utils.parser.utils.type_for_source( cwl_obj, cwl_obj.loadingOptions.fileuri + "#step1/echo_out_file" ) assert source_type == "File" def test_v1_0_type_for_source_with_id() -> None: """Test that the type is correctly inferred from a source id with CWL v1.0.""" uri = get_path("testdata/step_valuefrom5_wf_with_id_v1_0.cwl").as_uri() cwl_obj = load_document_by_uri(uri) source_type = cwl_utils.parser.utils.type_for_source( cwl_obj, cwl_obj.loadingOptions.fileuri + "#step1/echo_out_file" ) assert source_type == "File" def test_v1_0_type_for_stdout() -> None: """Test that the `stdout` type is correctly matched with the `File` type in CWL v1.0.""" uri = get_path("testdata/stdout-wf_v1_0.cwl").as_uri() cwl_obj = load_document_by_uri(uri) source_type = cwl_utils.parser.utils.type_for_source( cwl_obj, cwl_obj.outputs[0].outputSource ) assert source_type == "File" def test_v1_0_type_output_source_record() -> None: """Test that the type is correctly inferred from a record output source with CWL v1.0.""" uri = get_path("testdata/record-output-wf_v1_0.cwl").as_uri() cwl_obj = load_document_by_uri(uri) source_type = cwl_utils.parser.utils.type_for_source( process=cwl_obj, sourcenames=cwl_obj.outputs[0].outputSource, ) assert isinstance(source_type, cwl_utils.parser.cwl_v1_0.RecordSchema) fields = cast( MutableSequence[cwl_utils.parser.cwl_v1_0.RecordField], source_type.fields ) assert len(fields) == 2 assert fields[0].type_ == "File" assert fields[1].type_ == "File" def test_v1_0_type_for_output_source_with_single_scatter_step() -> None: """Test that the type is correctly inferred from a single scatter step with CWL v1.0.""" uri = get_path("testdata/scatter-wf1_v1_0.cwl").as_uri() cwl_obj = load_document_by_uri(uri) source_type = cwl_utils.parser.utils.type_for_source( process=cwl_obj, sourcenames=cwl_obj.outputs[0].outputSource, ) assert isinstance(source_type, cwl_utils.parser.cwl_v1_0.ArraySchema) assert source_type.items == "string" def test_v1_0_type_for_output_source_with_nested_crossproduct_scatter_step() -> None: """Test that the type is correctly inferred from a nested_crossproduct scatter step with CWL v1.0.""" uri = get_path("testdata/scatter-wf2_v1_0.cwl").as_uri() cwl_obj = load_document_by_uri(uri) source_type = cwl_utils.parser.utils.type_for_source( process=cwl_obj, sourcenames=cwl_obj.outputs[0].outputSource, ) assert isinstance(source_type, cwl_utils.parser.cwl_v1_0.ArraySchema) assert isinstance(source_type.items, cwl_utils.parser.cwl_v1_0.ArraySchema) assert source_type.items.items == "string" def test_v1_0_type_for_output_source_with_flat_crossproduct_scatter_step() -> None: """Test that the type is correctly inferred from a flat_crossproduct scatter step with CWL v1.0.""" uri = get_path("testdata/scatter-wf3_v1_0.cwl").as_uri() cwl_obj = load_document_by_uri(uri) source_type = cwl_utils.parser.utils.type_for_source( process=cwl_obj, sourcenames=cwl_obj.outputs[0].outputSource ) assert isinstance(source_type, cwl_utils.parser.cwl_v1_0.ArraySchema) assert source_type.items == "string" def test_v1_0_type_for_source_with_multiple_entries_merge_nested() -> None: """Test that the type is correctly inferred from a list of source ids and merge_nested with CWL v1.0.""" uri = get_path("testdata/count-lines6-wf_v1_0.cwl").as_uri() cwl_obj = load_document_by_uri(uri) source_type = cwl_utils.parser.utils.type_for_source( process=cwl_obj, sourcenames=cwl_obj.steps[0].in_[0].source, linkMerge=cwl_obj.steps[0].in_[0].linkMerge, ) assert isinstance(source_type, cwl_utils.parser.cwl_v1_0.ArraySchema) assert isinstance(source_type.items, cwl_utils.parser.cwl_v1_0.ArraySchema) assert source_type.items.items == "File" def test_v1_0_type_for_source_with_multiple_entries_merge_flattened() -> None: """Test that the type is correctly inferred from a list of source ids and merge_flattened with CWL v1.0.""" # noqa: B950 uri = get_path("testdata/count-lines7-wf_v1_0.cwl").as_uri() cwl_obj = load_document_by_uri(uri) source_type = cwl_utils.parser.utils.type_for_source( process=cwl_obj, sourcenames=cwl_obj.steps[0].in_[0].source, linkMerge=cwl_obj.steps[0].in_[0].linkMerge, ) assert isinstance(source_type, cwl_utils.parser.cwl_v1_0.ArraySchema) assert source_type.items == "File" def test_v1_0_type_for_source_with_single_entry_merge_nested() -> None: """Test that the type is correctly inferred from a single source id and merge_nested with CWL v1.0.""" uri = get_path("testdata/count-lines6-single-source-wf_v1_0.cwl").as_uri() cwl_obj = load_document_by_uri(uri) source_type = cwl_utils.parser.utils.type_for_source( process=cwl_obj, sourcenames=cwl_obj.steps[0].in_[0].source, linkMerge=cwl_obj.steps[0].in_[0].linkMerge, ) assert isinstance(source_type, cwl_utils.parser.cwl_v1_0.ArraySchema) assert isinstance(source_type.items, cwl_utils.parser.cwl_v1_0.ArraySchema) assert source_type.items.items == "File" def test_v1_0_type_for_source_with_single_entry_merge_flattened() -> None: """Test that the type is correctly inferred from a single source id and merge_flattened with CWL v1.0.""" uri = get_path("testdata/count-lines7-single-source-wf_v1_0.cwl").as_uri() cwl_obj = load_document_by_uri(uri) source_type = cwl_utils.parser.utils.type_for_source( process=cwl_obj, sourcenames=cwl_obj.steps[0].in_[0].source, linkMerge=cwl_obj.steps[0].in_[0].linkMerge, ) assert isinstance(source_type, cwl_utils.parser.cwl_v1_0.ArraySchema) assert source_type.items == "File" def test_v1_1_file_content_64_kB() -> None: """Test that reading file content is allowed up to 64kB in CWL v1.1.""" text = "a" * cwl_utils.parser.cwl_v1_1_utils.CONTENT_LIMIT with tempfile.TemporaryFile() as f: f.write(text.encode("utf-8")) f.seek(0) content = cwl_utils.parser.cwl_v1_1_utils.content_limit_respected_read(f) assert content == text def test_v1_1_file_content_larger_than_64_kB() -> None: """Test that reading file content is truncated to 64kB for larger files in CWL v1.1.""" text = "a" * (cwl_utils.parser.cwl_v1_1_utils.CONTENT_LIMIT + 1) with tempfile.TemporaryFile() as f: f.write(text.encode("utf-8")) f.seek(0) content = cwl_utils.parser.cwl_v1_1_utils.content_limit_respected_read(f) assert content == text[0 : cwl_utils.parser.cwl_v1_1_utils.CONTENT_LIMIT] def test_v_1_1_load_inputfile_with_format() -> None: """Test that File object with the `format` field is correctly loaded with CWL v1.1.""" doc_uri = get_path("testdata/formattest2_v1_1.cwl").as_uri() cwl_obj = load_document_by_uri(doc_uri) job_uri = get_path("testdata/formattest-job.json").as_uri() jobfile = cwl_utils.parser.utils.load_inputfile_by_uri( "v1.1", job_uri, cwl_obj.loadingOptions ) assert jobfile["input"].format == cwl_obj.inputs[0].format def test_v_1_1_load_inputfile_with_nested_array() -> None: """Test that nested arrays are preserved when loading an input file with CWL v1.1.""" uri = get_path("testdata/nested-array-job.yml").as_uri() jobfile = cwl_utils.parser.utils.load_inputfile_by_uri("v1.1", uri) assert isinstance(jobfile["letters"], MutableSequence) assert isinstance(jobfile["letters"][0], MutableSequence) assert jobfile["letters"][0][0] == "a" def test_v_1_1_load_inputfile_with_requirements() -> None: """Test that an input file with the cwl:requirements directive is correctly loaded with CWL v1.1.""" uri = get_path("testdata/env-job3.yaml").as_uri() jobfile = cwl_utils.parser.utils.load_inputfile_by_uri("v1.1", uri) assert isinstance( jobfile["cwl:requirements"][0], cwl_utils.parser.cwl_v1_1.EnvVarRequirement ) def test_v_1_1_load_inputfile_with_secondary_files() -> None: """Test that secondary files are treated as objects when loading an input file with CWL v1.1.""" uri = get_path("testdata/dir4-job.yml").as_uri() jobfile = cwl_utils.parser.utils.load_inputfile_by_uri("v1.1", uri) assert isinstance(jobfile["inf"].secondaryFiles[0], cwl_utils.parser.cwl_v1_1.File) assert isinstance( jobfile["inf"].secondaryFiles[1], cwl_utils.parser.cwl_v1_1.Directory ) def test_v1_1_stdout_to_file() -> None: """Test that stdout shortcut is converted to stdout parameter with CWL v1.1.""" clt = cwl_utils.parser.cwl_v1_1.CommandLineTool( inputs=[], outputs=[ cwl_utils.parser.cwl_v1_1.CommandOutputParameter(id="test", type_="stdout") ], ) cwl_utils.parser.cwl_v1_1_utils.convert_stdstreams_to_files(clt) assert clt.stdout is not None assert clt.stdout == clt.outputs[0].outputBinding.glob def test_v1_1_stdout_to_file_with_binding() -> None: """Test that outputBinding is not allowed with stdout shortcut with CWL v1.1.""" clt = cwl_utils.parser.cwl_v1_1.CommandLineTool( inputs=[], outputs=[ cwl_utils.parser.cwl_v1_1.CommandOutputParameter( id="test", type_="stdout", outputBinding=cwl_utils.parser.cwl_v1_1.CommandOutputBinding( glob="output.txt" ), ) ], ) with raises(ValidationException): cwl_utils.parser.cwl_v1_1_utils.convert_stdstreams_to_files(clt) def test_v1_1_stdout_to_file_preserve_original() -> None: """Test that stdout parameter prevails on stdout shortcut with CWL v1.1.""" clt = cwl_utils.parser.cwl_v1_1.CommandLineTool( inputs=[], outputs=[ cwl_utils.parser.cwl_v1_1.CommandOutputParameter(id="test", type_="stdout") ], stdout="original.txt", ) cwl_utils.parser.cwl_v1_1_utils.convert_stdstreams_to_files(clt) assert clt.stdout == "original.txt" assert clt.stdout == clt.outputs[0].outputBinding.glob def test_v1_1_stderr_to_file() -> None: """Test that stderr shortcut is converted to stderr parameter with CWL v1.1.""" clt = cwl_utils.parser.cwl_v1_1.CommandLineTool( inputs=[], outputs=[ cwl_utils.parser.cwl_v1_1.CommandOutputParameter(id="test", type_="stderr") ], ) cwl_utils.parser.cwl_v1_1_utils.convert_stdstreams_to_files(clt) assert clt.stderr is not None assert clt.stderr == clt.outputs[0].outputBinding.glob def test_v1_1_stderr_to_file_with_binding() -> None: """Test that outputBinding is not allowed with stderr shortcut with CWL v1.1.""" clt = cwl_utils.parser.cwl_v1_1.CommandLineTool( inputs=[], outputs=[ cwl_utils.parser.cwl_v1_1.CommandOutputParameter( id="test", type_="stderr", outputBinding=cwl_utils.parser.cwl_v1_1.CommandOutputBinding( glob="err.txt" ), ) ], ) with raises(ValidationException): cwl_utils.parser.cwl_v1_1_utils.convert_stdstreams_to_files(clt) def test_v1_1_stderr_to_file_preserve_original() -> None: """Test that stderr parameter prevails on stdout shortcut with CWL v1.1.""" clt = cwl_utils.parser.cwl_v1_1.CommandLineTool( inputs=[], outputs=[ cwl_utils.parser.cwl_v1_1.CommandOutputParameter(id="test", type_="stderr") ], stderr="original.txt", ) cwl_utils.parser.cwl_v1_1_utils.convert_stdstreams_to_files(clt) assert clt.stderr == "original.txt" assert clt.stderr == clt.outputs[0].outputBinding.glob def test_v1_1_stdin_to_file() -> None: """Test that stdin shortcut is converted to stdin parameter with CWL v1.1.""" clt = cwl_utils.parser.cwl_v1_1.CommandLineTool( inputs=[ cwl_utils.parser.cwl_v1_1.CommandInputParameter(id="test", type_="stdin") ], outputs=[], ) cwl_utils.parser.cwl_v1_1_utils.convert_stdstreams_to_files(clt) assert clt.stdin is not None def test_v1_1_stdin_to_file_with_binding() -> None: """Test that inputBinding is not allowed with stdin shortcut with CWL v1.1.""" clt = cwl_utils.parser.cwl_v1_1.CommandLineTool( inputs=[ cwl_utils.parser.cwl_v1_1.CommandInputParameter( id="test", type_="stdin", inputBinding=cwl_utils.parser.cwl_v1_1.CommandLineBinding( prefix="--test" ), ) ], outputs=[], ) with raises(ValidationException): cwl_utils.parser.cwl_v1_1_utils.convert_stdstreams_to_files(clt) def test_v1_1_stdin_to_file_fail_with_original() -> None: """Test that stdin shortcut fails when stdin parameter is defined with CWL v1.1.""" clt = cwl_utils.parser.cwl_v1_1.CommandLineTool( inputs=[ cwl_utils.parser.cwl_v1_1.CommandInputParameter(id="test", type_="stdin") ], outputs=[], stdin="original.txt", ) with raises(ValidationException): cwl_utils.parser.cwl_v1_1_utils.convert_stdstreams_to_files(clt) def test_v1_1_type_compare_list() -> None: """Test that the type comparison works correctly a list type with CWL v1.1.""" uri = get_path("testdata/echo_v1_1.cwl").as_uri() cwl_obj = load_document_by_uri(uri) assert cwl_utils.parser.cwl_v1_1_utils._compare_type( cwl_obj.inputs[0].type_, cwl_obj.inputs[0].type_ ) def test_v1_1_type_compare_record() -> None: """Test that the type comparison works correctly a record type with CWL v1.1.""" uri = get_path("testdata/record-output-wf_v1_1.cwl").as_uri() cwl_obj = load_document_by_uri(uri) source_type = cwl_utils.parser.utils.type_for_source( process=cwl_obj, sourcenames=cwl_obj.outputs[0].outputSource, ) assert cwl_utils.parser.cwl_v1_1_utils._compare_type(source_type, source_type) def test_v1_1_type_for_source() -> None: """Test that the type is correctly inferred from a source id with CWL v1.1.""" uri = get_path("testdata/step_valuefrom5_wf_v1_1.cwl").as_uri() cwl_obj = load_document_by_uri(uri) source_type = cwl_utils.parser.utils.type_for_source( cwl_obj, cwl_obj.loadingOptions.fileuri + "#step1/echo_out_file" ) assert source_type == "File" def test_v1_1_type_for_source_with_id() -> None: """Test that the type is correctly inferred from a source id with CWL v1.1.""" uri = get_path("testdata/step_valuefrom5_wf_with_id_v1_1.cwl").as_uri() cwl_obj = load_document_by_uri(uri) source_type = cwl_utils.parser.utils.type_for_source( cwl_obj, cwl_obj.loadingOptions.fileuri + "#step1/echo_out_file" ) assert source_type == "File" def test_v1_1_type_for_stdout() -> None: """Test that the `stdout` type is correctly matched with the `File` type in CWL v1.1.""" uri = get_path("testdata/stdout-wf_v1_1.cwl").as_uri() cwl_obj = load_document_by_uri(uri) source_type = cwl_utils.parser.utils.type_for_source( cwl_obj, cwl_obj.outputs[0].outputSource ) assert source_type == "File" def test_v1_1_type_output_source_record() -> None: """Test that the type is correctly inferred from a record output source with CWL v1.1.""" uri = get_path("testdata/record-output-wf_v1_1.cwl").as_uri() cwl_obj = load_document_by_uri(uri) source_type = cwl_utils.parser.utils.type_for_source( process=cwl_obj, sourcenames=cwl_obj.outputs[0].outputSource, ) assert isinstance(source_type, cwl_utils.parser.cwl_v1_1.RecordSchema) fields = cast( MutableSequence[cwl_utils.parser.cwl_v1_1.RecordField], source_type.fields ) assert len(fields) == 2 assert fields[0].type_ == "File" assert fields[1].type_ == "File" def test_v1_1_type_for_output_source_with_single_scatter_step() -> None: """Test that the type is correctly inferred from a single scatter step with CWL v1.1.""" uri = get_path("testdata/scatter-wf1_v1_1.cwl").as_uri() cwl_obj = load_document_by_uri(uri) source_type = cwl_utils.parser.utils.type_for_source( process=cwl_obj, sourcenames=cwl_obj.outputs[0].outputSource, ) assert isinstance(source_type, cwl_utils.parser.cwl_v1_1.ArraySchema) assert source_type.items == "string" def test_v1_1_type_for_output_source_with_nested_crossproduct_scatter_step() -> None: """Test that the type is correctly inferred from a nested_crossproduct scatter step with CWL v1.1.""" uri = get_path("testdata/scatter-wf2_v1_1.cwl").as_uri() cwl_obj = load_document_by_uri(uri) source_type = cwl_utils.parser.utils.type_for_source( process=cwl_obj, sourcenames=cwl_obj.outputs[0].outputSource, ) assert isinstance(source_type, cwl_utils.parser.cwl_v1_1.ArraySchema) assert isinstance(source_type.items, cwl_utils.parser.cwl_v1_1.ArraySchema) assert source_type.items.items == "string" def test_v1_1_type_for_output_source_with_flat_crossproduct_scatter_step() -> None: """Test that the type is correctly inferred from a flat_crossproduct scatter step with CWL v1.1.""" uri = get_path("testdata/scatter-wf3_v1_1.cwl").as_uri() cwl_obj = load_document_by_uri(uri) source_type = cwl_utils.parser.utils.type_for_source( process=cwl_obj, sourcenames=cwl_obj.outputs[0].outputSource, ) assert isinstance(source_type, cwl_utils.parser.cwl_v1_1.ArraySchema) assert source_type.items == "string" def test_v1_1_type_for_source_with_multiple_entries_merge_nested() -> None: """Test that the type is correctly inferred from a list of source ids and merge_nested with CWL v1.1.""" uri = get_path("testdata/count-lines6-wf_v1_1.cwl").as_uri() cwl_obj = load_document_by_uri(uri) source_type = cwl_utils.parser.utils.type_for_source( process=cwl_obj, sourcenames=cwl_obj.steps[0].in_[0].source, linkMerge=cwl_obj.steps[0].in_[0].linkMerge, ) assert isinstance(source_type, cwl_utils.parser.cwl_v1_1.ArraySchema) assert isinstance(source_type.items, cwl_utils.parser.cwl_v1_1.ArraySchema) assert source_type.items.items == "File" def test_v1_1_type_for_source_with_multiple_entries_merge_flattened() -> None: """Test that the type is correctly inferred from a list of source ids and merge_flattened with CWL v1.1.""" # noqa: B950 uri = get_path("testdata/count-lines7-wf_v1_1.cwl").as_uri() cwl_obj = load_document_by_uri(uri) source_type = cwl_utils.parser.utils.type_for_source( process=cwl_obj, sourcenames=cwl_obj.steps[0].in_[0].source, linkMerge=cwl_obj.steps[0].in_[0].linkMerge, ) assert isinstance(source_type, cwl_utils.parser.cwl_v1_1.ArraySchema) assert source_type.items == "File" def test_v1_1_type_for_source_with_single_entry_merge_nested() -> None: """Test that the type is correctly inferred from a single source id and merge_nested with CWL v1.1.""" uri = get_path("testdata/count-lines6-single-source-wf_v1_1.cwl").as_uri() cwl_obj = load_document_by_uri(uri) source_type = cwl_utils.parser.utils.type_for_source( process=cwl_obj, sourcenames=cwl_obj.steps[0].in_[0].source, linkMerge=cwl_obj.steps[0].in_[0].linkMerge, ) assert isinstance(source_type, cwl_utils.parser.cwl_v1_1.ArraySchema) assert isinstance(source_type.items, cwl_utils.parser.cwl_v1_1.ArraySchema) assert source_type.items.items == "File" def test_v1_1_type_for_source_with_single_entry_merge_flattened() -> None: """Test that the type is correctly inferred from a single source id and merge_flattened with CWL v1.1.""" uri = get_path("testdata/count-lines7-single-source-wf_v1_1.cwl").as_uri() cwl_obj = load_document_by_uri(uri) source_type = cwl_utils.parser.utils.type_for_source( process=cwl_obj, sourcenames=cwl_obj.steps[0].in_[0].source, linkMerge=cwl_obj.steps[0].in_[0].linkMerge, ) assert isinstance(source_type, cwl_utils.parser.cwl_v1_1.ArraySchema) assert source_type.items == "File" def test_v1_2_file_content_64_kB() -> None: """Test that reading file content is allowed up to 64kB in CWL v1.2.""" text = "a" * cwl_utils.parser.cwl_v1_2_utils.CONTENT_LIMIT with tempfile.TemporaryFile() as f: f.write(text.encode("utf-8")) f.seek(0) content = cwl_utils.parser.cwl_v1_2_utils.content_limit_respected_read(f) assert content == text def test_v1_2_file_content_larger_than_64_kB() -> None: """Test that reading file content fails for files larger than 64kB in CWL v1.0.""" text = "a" * (cwl_utils.parser.cwl_v1_2_utils.CONTENT_LIMIT + 1) with tempfile.TemporaryFile() as f: f.write(text.encode("utf-8")) f.seek(0) with raises(WorkflowException): cwl_utils.parser.cwl_v1_2_utils.content_limit_respected_read(f) def test_v_1_2_load_inputfile_with_format() -> None: """Test that File object with the `format` field is correctly loaded with CWL v1.2.""" cwl_uri = get_path("testdata/formattest2.cwl").as_uri() cwl_obj = load_document_by_uri(cwl_uri) job_uri = get_path("testdata/formattest-job.json").as_uri() jobfile = cwl_utils.parser.utils.load_inputfile_by_uri( "v1.2", job_uri, cwl_obj.loadingOptions ) assert jobfile["input"].format == cwl_obj.inputs[0].format def test_v_1_2_load_inputfile_with_nested_array() -> None: """Test that nested arrays are preserved when loading an input file with CWL v1.2.""" uri = get_path("testdata/nested-array-job.yml").as_uri() jobfile = cwl_utils.parser.utils.load_inputfile_by_uri("v1.2", uri) assert isinstance(jobfile["letters"], MutableSequence) assert isinstance(jobfile["letters"][0], MutableSequence) assert jobfile["letters"][0][0] == "a" def test_v_1_2_load_inputfile_with_requirements() -> None: """Test that an input file with the cwl:requirements directive is correctly loaded with CWL v1.2.""" uri = get_path("testdata/env-job3.yaml").as_uri() jobfile = cwl_utils.parser.utils.load_inputfile_by_uri("v1.2", uri) assert isinstance( jobfile["cwl:requirements"][0], cwl_utils.parser.cwl_v1_2.EnvVarRequirement ) def test_v_1_2_load_inputfile_with_secondary_files() -> None: """Test that secondary files are treated as objects when loading an input file with CWL v1.2.""" uri = get_path("testdata/dir4-job.yml").as_uri() jobfile = cwl_utils.parser.utils.load_inputfile_by_uri("v1.2", uri) assert isinstance(jobfile["inf"].secondaryFiles[0], cwl_utils.parser.cwl_v1_2.File) assert isinstance( jobfile["inf"].secondaryFiles[1], cwl_utils.parser.cwl_v1_2.Directory ) def test_v1_2_stdout_to_file() -> None: """Test that stdout shortcut is converted to stdout parameter with CWL v1.2.""" clt = cwl_utils.parser.cwl_v1_2.CommandLineTool( inputs=[], outputs=[ cwl_utils.parser.cwl_v1_2.CommandOutputParameter(id="test", type_="stdout") ], ) cwl_utils.parser.cwl_v1_2_utils.convert_stdstreams_to_files(clt) assert clt.stdout is not None assert clt.stdout == clt.outputs[0].outputBinding.glob def test_v1_2_stdout_to_file_with_binding() -> None: """Test that outputBinding is not allowed with stdout shortcut with CWL v1.2.""" clt = cwl_utils.parser.cwl_v1_2.CommandLineTool( inputs=[], outputs=[ cwl_utils.parser.cwl_v1_2.CommandOutputParameter( id="test", type_="stdout", outputBinding=cwl_utils.parser.cwl_v1_2.CommandOutputBinding( glob="output.txt" ), ) ], ) with raises(ValidationException): cwl_utils.parser.cwl_v1_2_utils.convert_stdstreams_to_files(clt) def test_v1_2_stdout_to_file_preserve_original() -> None: """Test that stdout parameter prevails on stdout shortcut with CWL v1.2.""" clt = cwl_utils.parser.cwl_v1_2.CommandLineTool( inputs=[], outputs=[ cwl_utils.parser.cwl_v1_2.CommandOutputParameter(id="test", type_="stdout") ], stdout="original.txt", ) cwl_utils.parser.cwl_v1_2_utils.convert_stdstreams_to_files(clt) assert clt.stdout == "original.txt" assert clt.stdout == clt.outputs[0].outputBinding.glob def test_v1_2_stderr_to_file() -> None: """Test that stderr shortcut is converted to stderr parameter with CWL v1.2.""" clt = cwl_utils.parser.cwl_v1_2.CommandLineTool( inputs=[], outputs=[ cwl_utils.parser.cwl_v1_2.CommandOutputParameter(id="test", type_="stderr") ], ) cwl_utils.parser.cwl_v1_2_utils.convert_stdstreams_to_files(clt) assert clt.stderr is not None assert clt.stderr == clt.outputs[0].outputBinding.glob def test_v1_2_stderr_to_file_with_binding() -> None: """Test that outputBinding is not allowed with stderr shortcut with CWL v1.2.""" clt = cwl_utils.parser.cwl_v1_2.CommandLineTool( inputs=[], outputs=[ cwl_utils.parser.cwl_v1_2.CommandOutputParameter( id="test", type_="stderr", outputBinding=cwl_utils.parser.cwl_v1_2.CommandOutputBinding( glob="err.txt" ), ) ], ) with raises(ValidationException): cwl_utils.parser.cwl_v1_2_utils.convert_stdstreams_to_files(clt) def test_v1_2_stderr_to_file_preserve_original() -> None: """Test that stderr parameter prevails on stdout shortcut with CWL v1.2.""" clt = cwl_utils.parser.cwl_v1_2.CommandLineTool( inputs=[], outputs=[ cwl_utils.parser.cwl_v1_2.CommandOutputParameter(id="test", type_="stderr") ], stderr="original.txt", ) cwl_utils.parser.cwl_v1_2_utils.convert_stdstreams_to_files(clt) assert clt.stderr == "original.txt" assert clt.stderr == clt.outputs[0].outputBinding.glob def test_v1_2_stdin_to_file() -> None: """Test that stdin shortcut is converted to stdin parameter with CWL v1.2.""" clt = cwl_utils.parser.cwl_v1_2.CommandLineTool( inputs=[ cwl_utils.parser.cwl_v1_2.CommandInputParameter(id="test", type_="stdin") ], outputs=[], ) cwl_utils.parser.cwl_v1_2_utils.convert_stdstreams_to_files(clt) assert clt.stdin is not None def test_v1_2_stdin_to_file_with_binding() -> None: """Test that inputBinding is not allowed with stdin shortcut with CWL v1.2.""" clt = cwl_utils.parser.cwl_v1_2.CommandLineTool( inputs=[ cwl_utils.parser.cwl_v1_2.CommandInputParameter( id="test", type_="stdin", inputBinding=cwl_utils.parser.cwl_v1_2.CommandLineBinding( prefix="--test" ), ) ], outputs=[], ) with raises(ValidationException): cwl_utils.parser.cwl_v1_2_utils.convert_stdstreams_to_files(clt) def test_v1_2_stdin_to_file_fail_with_original() -> None: """Test that stdin shortcut fails when stdin parameter is defined with CWL v1.2.""" clt = cwl_utils.parser.cwl_v1_2.CommandLineTool( inputs=[ cwl_utils.parser.cwl_v1_2.CommandInputParameter(id="test", type_="stdin") ], outputs=[], stdin="original.txt", ) with raises(ValidationException): cwl_utils.parser.cwl_v1_2_utils.convert_stdstreams_to_files(clt) def test_v1_2_type_compare_list() -> None: """Test that the type comparison works correctly a list type with CWL v1.2.""" uri = get_path("testdata/echo_v1_2.cwl").as_uri() cwl_obj = load_document_by_uri(uri) assert cwl_utils.parser.cwl_v1_2_utils._compare_type( cwl_obj.inputs[0].type_, cwl_obj.inputs[0].type_ ) def test_v1_2_type_compare_record() -> None: """Test that the type comparison works correctly a record type with CWL v1.2.""" uri = get_path("testdata/record-output-wf_v1_2.cwl").as_uri() cwl_obj = load_document_by_uri(uri) source_type = cwl_utils.parser.utils.type_for_source( process=cwl_obj, sourcenames=cwl_obj.outputs[0].outputSource, ) assert cwl_utils.parser.cwl_v1_2_utils._compare_type(source_type, source_type) def test_v1_2_type_for_source() -> None: """Test that the type is correctly inferred from a source id with CWL v1.2.""" uri = get_path("testdata/step_valuefrom5_wf_v1_2.cwl").as_uri() cwl_obj = load_document_by_uri(uri) source_type = cwl_utils.parser.utils.type_for_source( cwl_obj, cwl_obj.loadingOptions.fileuri + "#step1/echo_out_file" ) assert source_type == "File" def test_v1_2_type_for_source_with_id() -> None: """Test that the type is correctly inferred from a source id with CWL v1.2.""" uri = get_path("testdata/step_valuefrom5_wf_with_id_v1_2.cwl").as_uri() cwl_obj = load_document_by_uri(uri) source_type = cwl_utils.parser.utils.type_for_source( cwl_obj, cwl_obj.loadingOptions.fileuri + "#step1/echo_out_file" ) assert source_type == "File" def test_v1_2_type_for_stdout() -> None: """Test that the `stdout` type is correctly matched with the `File` type in CWL v1.2.""" uri = get_path("testdata/stdout-wf_v1_2.cwl").as_uri() cwl_obj = load_document_by_uri(uri) source_type = cwl_utils.parser.utils.type_for_source( cwl_obj, cwl_obj.outputs[0].outputSource ) assert source_type == "File" def test_v1_2_type_output_source_record() -> None: """Test that the type is correctly inferred from a record output source with CWL v1.2.""" uri = get_path("testdata/record-output-wf_v1_2.cwl").as_uri() cwl_obj = load_document_by_uri(uri) source_type = cwl_utils.parser.utils.type_for_source( process=cwl_obj, sourcenames=cwl_obj.outputs[0].outputSource, ) assert isinstance(source_type, cwl_utils.parser.cwl_v1_2.RecordSchema) fields = cast( MutableSequence[cwl_utils.parser.cwl_v1_2.RecordField], source_type.fields ) assert len(fields) == 2 assert fields[0].type_ == "File" assert fields[1].type_ == "File" def test_v1_2_type_for_output_source_with_single_scatter_step() -> None: """Test that the type is correctly inferred from a single scatter step with CWL v1.2.""" uri = get_path("testdata/scatter-wf1_v1_2.cwl").as_uri() cwl_obj = load_document_by_uri(uri) source_type = cwl_utils.parser.utils.type_for_source( process=cwl_obj, sourcenames=cwl_obj.outputs[0].outputSource, ) assert isinstance(source_type, cwl_utils.parser.cwl_v1_2.ArraySchema) assert source_type.items == "string" def test_v1_2_type_for_output_source_with_nested_crossproduct_scatter_step() -> None: """Test that the type is correctly inferred from a nested_crossproduct scatter step with CWL v1.2.""" uri = get_path("testdata/scatter-wf2_v1_2.cwl").as_uri() cwl_obj = load_document_by_uri(uri) source_type = cwl_utils.parser.utils.type_for_source( process=cwl_obj, sourcenames=cwl_obj.outputs[0].outputSource, ) assert isinstance(source_type, cwl_utils.parser.cwl_v1_2.ArraySchema) assert isinstance(source_type.items, cwl_utils.parser.cwl_v1_2.ArraySchema) assert source_type.items.items == "string" def test_v1_2_type_for_output_source_with_flat_crossproduct_scatter_step() -> None: """Test that the type is correctly inferred from a flat_crossproduct scatter step with CWL v1.2.""" uri = get_path("testdata/scatter-wf3_v1_2.cwl").as_uri() cwl_obj = load_document_by_uri(uri) source_type = cwl_utils.parser.utils.type_for_source( process=cwl_obj, sourcenames=cwl_obj.outputs[0].outputSource, ) assert isinstance(source_type, cwl_utils.parser.cwl_v1_2.ArraySchema) assert source_type.items == "string" def test_v1_2_type_for_source_with_multiple_entries_merge_nested() -> None: """Test that the type is correctly inferred from a list of source ids and merge_nested with CWL v1.2.""" uri = get_path("testdata/count-lines6-wf_v1_2.cwl").as_uri() cwl_obj = load_document_by_uri(uri) source_type = cwl_utils.parser.utils.type_for_source( process=cwl_obj, sourcenames=cwl_obj.steps[0].in_[0].source, linkMerge=cwl_obj.steps[0].in_[0].linkMerge, ) assert isinstance(source_type, cwl_utils.parser.cwl_v1_2.ArraySchema) assert isinstance(source_type.items, cwl_utils.parser.cwl_v1_2.ArraySchema) assert source_type.items.items == "File" def test_v1_2_type_for_source_with_multiple_entries_merge_flattened() -> None: """Test that the type is correctly inferred from a list of source ids and merge_flattened with CWL v1.2.""" # noqa: B950 uri = get_path("testdata/count-lines7-wf_v1_2.cwl").as_uri() cwl_obj = load_document_by_uri(uri) source_type = cwl_utils.parser.utils.type_for_source( process=cwl_obj, sourcenames=cwl_obj.steps[0].in_[0].source, linkMerge=cwl_obj.steps[0].in_[0].linkMerge, ) assert isinstance(source_type, cwl_utils.parser.cwl_v1_2.ArraySchema) assert source_type.items == "File" def test_v1_2_type_for_source_with_single_entry_merge_nested() -> None: """Test that the type is correctly inferred from a single source id and merge_nested with CWL v1.2.""" uri = get_path("testdata/count-lines6-single-source-wf_v1_2.cwl").as_uri() cwl_obj = load_document_by_uri(uri) source_type = cwl_utils.parser.utils.type_for_source( process=cwl_obj, sourcenames=cwl_obj.steps[0].in_[0].source, linkMerge=cwl_obj.steps[0].in_[0].linkMerge, ) assert isinstance(source_type, cwl_utils.parser.cwl_v1_2.ArraySchema) assert isinstance(source_type.items, cwl_utils.parser.cwl_v1_2.ArraySchema) assert source_type.items.items == "File" def test_v1_2_type_for_source_with_single_entry_merge_flattened() -> None: """Test that the type is correctly inferred from a single source id and merge_flattened with CWL v1.2.""" uri = get_path("testdata/count-lines7-single-source-wf_v1_2.cwl").as_uri() cwl_obj = load_document_by_uri(uri) source_type = cwl_utils.parser.utils.type_for_source( process=cwl_obj, sourcenames=cwl_obj.steps[0].in_[0].source, linkMerge=cwl_obj.steps[0].in_[0].linkMerge, ) assert isinstance(source_type, cwl_utils.parser.cwl_v1_2.ArraySchema) assert source_type.items == "File" def test_v1_2_type_for_source_with_multiple_entries_first_non_null() -> None: """Test that the type is correctly inferred from a list of source ids and first_non_null with CWL v1.2.""" uri = get_path("testdata/cond-wf-003.1.cwl").as_uri() cwl_obj = load_document_by_uri(uri) source_type = cwl_utils.parser.utils.type_for_source( process=cwl_obj, sourcenames=cwl_obj.outputs[0].outputSource, pickValue=cwl_obj.outputs[0].pickValue, ) assert source_type == "string" def test_v1_2_type_for_source_with_multiple_entries_the_only_non_null() -> None: """Test that the type is correctly inferred from a list of source ids and the_only_non_null with CWL v1.2.""" # noqa: B950 uri = get_path("testdata/cond-wf-004.1.cwl").as_uri() cwl_obj = load_document_by_uri(uri) source_type = cwl_utils.parser.utils.type_for_source( process=cwl_obj, sourcenames=cwl_obj.outputs[0].outputSource, pickValue=cwl_obj.outputs[0].pickValue, ) assert source_type == "string" def test_v1_2_type_for_source_with_multiple_entries_all_non_null() -> None: """Test that the type is correctly inferred from a list of source ids and all_non_null with CWL v1.2.""" uri = get_path("testdata/cond-wf-005.1.cwl").as_uri() cwl_obj = load_document_by_uri(uri) source_type = cwl_utils.parser.utils.type_for_source( process=cwl_obj, sourcenames=cwl_obj.outputs[0].outputSource, pickValue=cwl_obj.outputs[0].pickValue, ) assert isinstance(source_type, cwl_utils.parser.cwl_v1_2.ArraySchema) assert source_type.items == "string" def test_v1_2_type_for_source_with_single_entry_first_non_null() -> None: """Test that the type is correctly inferred from a single source id and first_non_null with CWL v1.2.""" uri = get_path("testdata/cond-single-source-wf-003.1.cwl").as_uri() cwl_obj = load_document_by_uri(uri) source_type = cwl_utils.parser.utils.type_for_source( process=cwl_obj, sourcenames=cwl_obj.outputs[0].outputSource, pickValue=cwl_obj.outputs[0].pickValue, ) assert source_type == "string" def test_v1_2_type_for_source_with_single_entry_the_only_non_null() -> None: """Test that the type is correctly inferred from a single source id and the_only_non_null with CWL v1.2.""" # noqa: B950 uri = get_path("testdata/cond-single-source-wf-004.1.cwl").as_uri() cwl_obj = load_document_by_uri(uri) source_type = cwl_utils.parser.utils.type_for_source( process=cwl_obj, sourcenames=cwl_obj.outputs[0].outputSource, pickValue=cwl_obj.outputs[0].pickValue, ) assert source_type == "string" def test_v1_2_type_for_source_with_single_entry_all_non_null() -> None: """Test that the type is correctly inferred from a single source id and all_non_null with CWL v1.2.""" uri = get_path("testdata/cond-single-source-wf-005.1.cwl").as_uri() cwl_obj = load_document_by_uri(uri) source_type = cwl_utils.parser.utils.type_for_source( process=cwl_obj, sourcenames=cwl_obj.outputs[0].outputSource, pickValue=cwl_obj.outputs[0].pickValue, ) assert isinstance(source_type, cwl_utils.parser.cwl_v1_2.ArraySchema) assert source_type.items == "string" cwl_utils-0.41/cwl_utils/tests/test_subscope.py0000644000000000000000000000234513615410400016772 0ustar00# SPDX-License-Identifier: Apache-2.0 """Test that scoping of identifiers in Workflow.steps[].run is correct.""" from cwl_utils.parser import Workflow, load_document_by_uri from .util import get_path def test_workflow_step_process_scope_v1_0() -> None: """CWL v1.0 IDs under Workflow.steps[].run should not be scoped in the "run" scope.""" uri = get_path("testdata/workflow_input_format_expr.cwl").as_uri() cwl_obj: Workflow = load_document_by_uri(uri) assert cwl_obj.steps[0].run.inputs[0].id.endswith("#format_extract/target") def test_workflow_step_process_scope_v1_1() -> None: """CWL v1.1 IDs under Workflow.steps[].run should be scoped in the "run" scope.""" uri = get_path("testdata/workflow_input_format_expr_v1_1.cwl").as_uri() cwl_obj: Workflow = load_document_by_uri(uri) assert cwl_obj.steps[0].run.inputs[0].id.endswith("#format_extract/run/target") def test_workflow_step_process_scope_v1_2() -> None: """CWL v1.2 IDs under Workflow.steps[].run should be scoped in the "run" scope.""" uri = get_path("testdata/workflow_input_format_expr_v1_2.cwl").as_uri() cwl_obj: Workflow = load_document_by_uri(uri) assert cwl_obj.steps[0].run.inputs[0].id.endswith("#format_extract/run/target") cwl_utils-0.41/cwl_utils/tests/test_utils.py0000644000000000000000000000100113615410400016273 0ustar00from urllib.parse import urlparse from cwl_utils.utils import resolved_path def test_resoled_path() -> None: base_url = urlparse( "schemas/bclconvert-run-configuration/2.0.0--4.0.3/bclconvert-run-configuration__2.0.0--4.0.3.yaml" ) link = "../../../schemas/samplesheet/2.0.0--4.0.3/samplesheet__2.0.0--4.0.3.yaml#samplesheet" rpath = resolved_path(base_url, link) assert rpath == urlparse( "schemas/samplesheet/2.0.0--4.0.3/samplesheet__2.0.0--4.0.3.yaml#samplesheet" ) cwl_utils-0.41/cwl_utils/tests/util.py0000644000000000000000000000233513615410400015064 0ustar00import atexit import os import shutil from contextlib import ExitStack from importlib.resources import as_file, files from pathlib import Path import pytest def get_path(filename: str) -> Path: """Get the filepath for a given test file.""" # normalizing path depending on OS or else it will cause problem when joining path filename = os.path.normpath(filename) file_manager = ExitStack() atexit.register(file_manager.close) traversable = files("cwl_utils") / filename filepath = file_manager.enter_context(as_file(traversable)) return filepath.resolve() def get_data(filename: str) -> str: return str(get_path(filename)) needs_docker = pytest.mark.skipif( not bool(shutil.which("docker")), reason="Requires the docker executable on the system path.", ) needs_singularity = pytest.mark.skipif( not bool(shutil.which("singularity")), reason="Requires the singularity executable on the system path.", ) needs_podman = pytest.mark.skipif( not bool(shutil.which("podman")), reason="Requires the podman executable on the system path.", ) needs_udocker = pytest.mark.skipif( not bool(shutil.which("udocker")), reason="Requires the udocker executable on the system path.", ) cwl_utils-0.41/docs/Makefile0000644000000000000000000000117213615410400012754 0ustar00# Minimal makefile for Sphinx documentation # # You can set these variables from the command line, and also # from the environment for the first two. SPHINXOPTS ?= SPHINXBUILD ?= sphinx-build SOURCEDIR = . BUILDDIR = _build # Put it first so that "make" without argument is like "make help". help: @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) .PHONY: help Makefile # Catch-all target: route all unknown targets to Sphinx using the new # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). %: Makefile @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) cwl_utils-0.41/docs/conf.py0000644000000000000000000000660013615410400012614 0ustar00# Configuration file for the Sphinx documentation builder. # # This file only contains a selection of the most common options. For a full # list see the documentation: # https://www.sphinx-doc.org/en/master/usage/configuration.html # -- Path setup -------------------------------------------------------------- import importlib.metadata # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. # import os import sys import time from datetime import datetime, timezone sys.path.insert(0, os.path.abspath("..")) # -- Project information ----------------------------------------------------- build_date = datetime.fromtimestamp( int(os.environ.get("SOURCE_DATE_EPOCH", time.time())), timezone.utc ) project = "cwl-utils: Python utilities Common Workflow Language documents" copyright = f"2019 — {build_date.year} CWL Community" author = "Common Workflow Language Project contributors" # -- General configuration --------------------------------------------------- # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ "sphinx.ext.autodoc", "sphinx.ext.autosummary", "sphinx.ext.intersphinx", "sphinx.ext.inheritance_diagram", "autoapi.extension", "sphinx_autodoc_typehints", "sphinx_rtd_theme", "sphinxcontrib.autoprogram", ] intersphinx_mapping = { "python": ("https://docs.python.org/3", None), "schema_salad": ("https://schema-salad.readthedocs.io/en/stable/", None), "rdflib": ("https://rdflib.readthedocs.io/en/6.2.0/", None), # "ruamel.yaml": ("https://yaml.readthedocs.io/en/stable/", None), } # Add any paths that contain templates here, relative to this directory. templates_path = ["_templates"] # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. # This pattern also affects html_static_path and html_extra_path. exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"] # -- Options for HTML output ------------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. # html_theme = "sphinx_rtd_theme" # html_logo = "_static/logo.png" html_favicon = "_static/favicon.ico" html_theme_options = { "collapse_navigation": False, } # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ["_static"] release = importlib.metadata.version("cwl_utils") version = ".".join(release.split(".")[:2]) autoapi_dirs = ["../cwl_utils"] autodoc_typehints = "description" autoapi_keep_files = True autoapi_ignore = ["*migrations*", "*.pyi"] autoapi_options = [ "members", "undoc-members", "show-inheritance", "show-inheritance-diagram", "show-module-summary", "imported-members", "special-members", ] # sphinx-autodoc-typehints always_document_param_types = True # If False, do not add type info for undocumented parameters. # If True, add stub documentation for undocumented parameters to be able to add type info. cwl_utils-0.41/docs/index.rst0000644000000000000000000000214613615410400013157 0ustar00====================================================== Python classes for loading, manipulating CWL documents ====================================================== This is the reference implementation of the Common Workflow Language. It is intended to be feature complete and provide comprehensive validation of CWL files as well as provide other tools related to working with CWL. Modules ======= .. toctree:: :maxdepth: 2 :caption: Contents: autoapi/index Included Utility Programs ========================= .. autoprogram:: cwl_utils.cite_extract:arg_parser() :prog: cwl-cite-extract .. autoprogram:: cwl_utils.docker_extract:arg_parser() :prog: cwl-docker-extract .. autoprogram:: cwl_utils.expression_refactor:arg_parser() :prog: cwl-expression-refactor .. autoprogram:: cwl_utils.graph_split:arg_parser() :prog: cwl-graph-split .. autoprogram:: cwl_utils.normalizer:arg_parser() :prog: cwl-normalizer .. autoprogram:: cwl_utils.inputs_schema_gen:arg_parser() :prog: cwl-inputs-schema-gen Indices and tables ================== * :ref:`genindex` * :ref:`modindex` * :ref:`search` cwl_utils-0.41/docs/make.bat0000644000000000000000000000143313615410400012721 0ustar00@ECHO OFF pushd %~dp0 REM Command file for Sphinx documentation if "%SPHINXBUILD%" == "" ( set SPHINXBUILD=sphinx-build ) set SOURCEDIR=. set BUILDDIR=_build if "%1" == "" goto help %SPHINXBUILD% >NUL 2>NUL if errorlevel 9009 ( echo. echo.The 'sphinx-build' command was not found. Make sure you have Sphinx echo.installed, then set the SPHINXBUILD environment variable to point echo.to the full path of the 'sphinx-build' executable. Alternatively you echo.may add the Sphinx directory to PATH. echo. echo.If you don't have Sphinx installed, grab it from echo.http://sphinx-doc.org/ exit /b 1 ) %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% goto end :help %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% :end popd cwl_utils-0.41/docs/requirements.txt0000644000000000000000000000014713615410400014601 0ustar00sphinx >= 2.2, < 10 sphinx-rtd-theme sphinx-autoapi sphinx-autodoc-typehints sphinxcontrib-autoprogram cwl_utils-0.41/docs/_static/favicon.ico0000644000000000000000000003535613615410400015076 0ustar0000 ¨%6  ¨Þ% h†6(0` $ÿÿÿÍÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÓÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüûþÿýûþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿûùýÿºŸâÿ¼¡ãÿûùþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿûùýÿ·žáÿvDÆÿwEÇÿ¹ âÿûúþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿûúþÿ¶žáÿrDÆÿo?Åÿo?ÅÿrDÆÿȶéÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿûúþÿµŸáÿnCÅÿj>Ãÿk?Ãÿi<ÃÿŒhÑÿçßöÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿûúþÿ³ŸáÿjBÄÿf=Âÿg>Âÿe;Áÿ‡fÏÿåÞõÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿûûþÿ±ŸàÿfAÂÿa;Áÿb<Áÿa;ÀÿƒeÎÿäÝôÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿôñûÿˆnÐÿZ7¾ÿ];¿ÿ];¿ÿ\:¿ÿ¤‘Ûÿýüþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿäßõÿ}eÍÿV7½ÿX9¾ÿX8¾ÿ_AÁÿ²¤áÿüûþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿãÞôÿxbËÿQ5¼ÿT8½ÿS7¼ÿY?¿ÿ°¤àÿüüþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿàÜóÿs`ÉÿL4»ÿN7»ÿM6»ÿU>¾ÿ°¥áÿüüþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÞÛóÿn^ÈÿG3¹ÿJ6ºÿI4ºÿQ=½ÿ®¥áÿüüþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÜÙòÿi[ÇÿC3¹ÿE5ºÿC3¹ÿL<¼ÿ¬¦àÿüüþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÙÖñÿYM¿ÿ>1¸ÿ@3¸ÿ>2¸ÿF:»ÿ´¯ãÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¿¹ÙÿG7—ÿ8-¬ÿ:1¸ÿ8/¶ÿPH¿ÿÈÅëÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¾¹ÜÿF7”ÿ1ÿ4!†ÿ3*©ÿJF¾ÿÄÂéÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¾ºÞÿG:›ÿ1 ˆÿ3 ÿ0vÿI9ÿÂÀæÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¾»áÿG<£ÿ1#ÿ3#‰ÿ0ÿK8ˆÿÅ¿×ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¾¼ãÿG>ªÿ2&˜ÿ4%‘ÿ0 ‡ÿK:ÿÅÀÚÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¾¼åÿGA±ÿ2( ÿ4(™ÿ2$‘ÿM?˜ÿÆÀÜÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿïïùÿb]Áÿ0(¨ÿ4*¡ÿ4(™ÿ2$‘ÿ”ŒÂÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÇÆéÿMG³ÿ1( ÿ4(™ÿ3$‘ÿG9•ÿ¼¶ÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÈÆçÿMD¬ÿ1%˜ÿ4%‘ÿ1 ˆÿE4Œÿ¼µÔÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÈÅåÿMB¥ÿ1#ÿ3#‰ÿ1ÿE1…ÿ¼´ÑÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÈÄãÿM@žÿ0 ˆÿ3 ÿ1vÿD1‚ÿ¼¸ÞÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÇÃàÿL>—ÿ0ÿ3}ÿ1&œÿFB»ÿ½»çÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÈÄÞÿM=–ÿ5)¢ÿ81·ÿ6/¶ÿJC½ÿ½ºçÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿçåöÿf\Ãÿ;0·ÿ=2¸ÿ<1¸ÿ;0·ÿŽˆÖÿüüþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿâàõÿrgËÿ@2¹ÿA3¹ÿA3¹ÿA4¹ÿ‰€ÓÿñðúÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÞÛóÿoaÉÿC2¹ÿE5ºÿE4ºÿG6ºÿ†ÖÿóòûÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÙÕñÿl\ÇÿH3¹ÿJ6ºÿI5ºÿL8»ÿ—ŒØÿõôûÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÔÎïÿjWÆÿL4ºÿN7»ÿM6»ÿQ:¼ÿž’Úÿ÷öüÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÎÆìÿjRÅÿP5¼ÿS8¼ÿR7¼ÿX?¿ÿ§™Ýÿùøýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüûþÿ–„×ÿS5¼ÿV9¾ÿW9¾ÿU7½ÿu]ÊÿëèøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿëèøÿˆqÑÿY8¾ÿZ:¿ÿZ:¿ÿ\;¿ÿ—‚×ÿóñûÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿëç÷ÿ‹rÑÿ]:¿ÿ_;Àÿ_;Àÿ_;Àÿ›„×ÿôñûÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿìçøÿŽsÒÿb;Áÿc=Áÿc<Áÿc<ÁÿŸ‡Ùÿõòûÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿìçøÿ‘sÓÿf<Âÿg>Âÿg=Âÿg>Âÿ¢ˆÚÿõóûÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿìçøÿ“sÔÿj=Ãÿk?Ãÿk>Ãÿk?Äÿ¥ŠÛÿöóüÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿíçøÿ–tÕÿm>Äÿo@Åÿo?Åÿn?Äÿ¯”ßÿýüÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿíçøÿ˜tÕÿq?Åÿr?ÅÿzKÈÿdzèÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿíæøÿ™rÔÿ}KÉÿDzèÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿìä÷ÿÖÅîÿýüþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÆÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÍ( @ ÿÿÿëÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿîÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýüþÿýüþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿûùýÿº âÿ»¢ãÿûúþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿûúþÿ¶žâÿsCÆÿrCÆÿÁ­æÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿûúþÿ´ŸáÿmCÅÿh;Âÿ}WËÿÙÍðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüûþÿ±žàÿgAÃÿa:ÀÿwUÉÿÖÌïÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøöýÿ“}ÕÿZ8¾ÿZ8¾ÿ€gÍÿíêøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿîêùÿ‰tÑÿS6¼ÿT7½ÿˆuÑÿíêøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿìéøÿ‚qÏÿK4ºÿL5ºÿ„uÐÿíëùÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿêè÷ÿ|oÎÿF5ºÿD3¹ÿ€uÐÿìêøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÚ×îÿRF·ÿ=1¸ÿ;/·ÿš“Úÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿóòùÿ…|¸ÿ6%ˆÿ3(£ÿa\ÆÿÜÛóÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿóòúÿ…}Àÿ3$‹ÿ0|ÿ_PšÿÜÚðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿóòúÿ…Çÿ4(˜ÿ0 ‰ÿ`QœÿÝÚèÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøøýÿ‡„Ïÿ4+£ÿ1%–ÿZM¢ÿÞÛëÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿùùýÿŠÑÿ5,¤ÿ1%–ÿWJ ÿÙÖèÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿõõûÿŒ†Êÿ5)˜ÿ0 ‰ÿZK˜ÿØÔåÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿõõûÿŒ„Ãÿ5%Œÿ/|ÿZI’ÿØÖìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿõõúÿŒƒ¼ÿ7%…ÿ2%šÿ\XÃÿØ×ñÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿâàòÿXM¶ÿ:/¶ÿ7-¶ÿ„}ÒÿûûþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿëêøÿwÐÿC5ºÿ@1¸ÿlaÈÿÝÚóÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿèå÷ÿ~oÎÿG4ºÿG3¹ÿufËÿâàôÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿäßõÿ|iÍÿM5»ÿO7»ÿ~mÎÿæãöÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿûûþÿ“ÕÿR4¼ÿT7½ÿiOÅÿßÙóÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÙÒðÿvZÉÿY8¾ÿ^=Àÿ ŒÚÿöôüÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÜÔñÿ{\Ëÿ`9Àÿc=Áÿ¤ŽÛÿ÷õüÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÝÔòÿ€]Ìÿf;Âÿi?Ãÿ©ÝÿøõüÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÞÓòÿ…^Îÿl=Ãÿn@Äÿ±˜àÿýýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿßÔòÿ‰^ÎÿxGÇÿ­æÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿßÒòÿ̸êÿýûþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿèÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿë(  ÿÿÿûÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýûþÿýûþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿûùþÿ¹¡âÿ¿©åÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýüþÿ±žàÿrLÇÿÈ·éÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿûúþÿŸŒÚÿeIÃÿÏÇìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿõóûÿ’…ÖÿbQÄÿÌÇìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÄ¿ßÿB4¨ÿ‘‹ÖÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÏÍéÿUI¢ÿzn®ÿîí÷ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ÷÷ýÿqkÀÿF:ÿÚ×éÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÒÐêÿWK¢ÿwjªÿíìöÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÈÄáÿB5¥ÿ‰ƒÒÿüüþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿóñûÿ’†Öÿ[MÂÿ½éÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüüþÿ›‹ÙÿY@¿ÿŽéÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿĸèÿnMÆÿ©•ÝÿùøýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿɺêÿxOÉÿ³›àÿþýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿμëÿÄ®çÿþýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿûÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿûcwl_utils-0.41/lint-requirements.txt0000644000000000000000000000007213615410400014612 0ustar00flake8-bugbear < 25.12 black == 26.* codespell isort >= 5 cwl_utils-0.41/load_cwl_by_path.py0000755000000000000000000000000013615410400023233 2cwl_utils/tests/load_cwl_by_path.pyustar00cwl_utils-0.41/mypy-requirements.txt0000644000000000000000000000010613615410400014640 0ustar00mypy==1.19.1 types-requests types-jsonschema types-setuptools>=57.4.0 cwl_utils-0.41/mypy-stubs/cwlformat/__init__.pyi0000644000000000000000000000000013615410400016765 0ustar00cwl_utils-0.41/mypy-stubs/cwlformat/formatter.pyi0000644000000000000000000000012613615410400017242 0ustar00from typing import Any, Dict def stringify_dict(as_dict: dict[str, Any]) -> str: ... cwl_utils-0.41/mypy-stubs/rdflib/__init__.pyi0000644000000000000000000000241413615410400016244 0ustar00from rdflib.graph import ConjunctiveGraph as ConjunctiveGraph from rdflib.graph import Graph as Graph from rdflib.namespace import CSVW as CSVW from rdflib.namespace import DC as DC from rdflib.namespace import DCAT as DCAT from rdflib.namespace import DCTERMS as DCTERMS from rdflib.namespace import DOAP as DOAP from rdflib.namespace import FOAF as FOAF from rdflib.namespace import ODRL2 as ODRL2 from rdflib.namespace import ORG as ORG from rdflib.namespace import OWL as OWL from rdflib.namespace import PROF as PROF from rdflib.namespace import PROV as PROV from rdflib.namespace import QB as QB from rdflib.namespace import RDF as RDF from rdflib.namespace import RDFS as RDFS from rdflib.namespace import SDO as SDO from rdflib.namespace import SH as SH from rdflib.namespace import SKOS as SKOS from rdflib.namespace import SOSA as SOSA from rdflib.namespace import SSN as SSN from rdflib.namespace import TIME as TIME from rdflib.namespace import VOID as VOID from rdflib.namespace import XMLNS as XMLNS from rdflib.namespace import XSD as XSD from rdflib.namespace import Namespace as Namespace from rdflib.term import BNode as BNode from rdflib.term import Literal as Literal from rdflib.term import URIRef as URIRef from rdflib.term import Variable as Variable __version__: str cwl_utils-0.41/mypy-stubs/rdflib/collection.pyi0000644000000000000000000000127513615410400016644 0ustar00from collections.abc import Iterator from typing import Any from rdflib.graph import Graph from rdflib.term import Node class Collection: graph: Graph uri: Node def __init__(self, graph: Graph, uri: Node, seq: Any = ...) -> None: ... def n3(self) -> str: ... def __len__(self) -> int: ... def index(self, item: Any) -> int: ... def __getitem__(self, key: str) -> Any: ... def __setitem__(self, key: str, value: Any) -> None: ... def __delitem__(self, key: str) -> None: ... def __iter__(self) -> Iterator[Any]: ... def append(self, item: Any) -> Collection: ... def __iadd__(self, other: Any) -> Collection: ... def clear(self) -> Collection: ... cwl_utils-0.41/mypy-stubs/rdflib/compare.pyi0000644000000000000000000000024313615410400016131 0ustar00from rdflib.graph import ConjunctiveGraph, Graph class IsomorphicGraph(ConjunctiveGraph): pass def to_isomorphic(graph: Graph = ...) -> IsomorphicGraph: ... cwl_utils-0.41/mypy-stubs/rdflib/graph.pyi0000644000000000000000000001777413615410400015625 0ustar00import pathlib from collections.abc import Iterable, Iterator from typing import ( IO, Any, List, Optional, Tuple, Union, overload, ) from builtins import set as _set from rdflib import query from rdflib.collection import Collection from rdflib.paths import Path from rdflib.resource import Resource from rdflib.term import BNode, Identifier, Node class Graph(Node): base: Any = ... context_aware: bool = ... formula_aware: bool = ... default_union: bool = ... def __init__( self, store: str = ..., identifier: Any | None = ..., namespace_manager: Any | None = ..., base: Any | None = ..., ) -> None: ... store: Any = ... identifier: Any = ... namespace_manager: Any = ... def toPython(self) -> str: ... def destroy(self, configuration: Any) -> None: ... def commit(self) -> None: ... def rollback(self) -> None: ... def open(self, configuration: Any, create: bool = ...) -> Any: ... def close(self, commit_pending_transaction: bool = ...) -> None: ... def add(self, triple: Any) -> None: ... def addN(self, quads: Any) -> None: ... def remove(self, triple: Any) -> None: ... def triples( self, triple: tuple[ str | Identifier | None, str | Identifier | None, Identifier | None, ], ) -> Iterator[tuple[Identifier, Identifier, Identifier]]: ... def __getitem__( self, item: slice | Path | Node ) -> Iterator[ tuple[Identifier, Identifier, Identifier] | tuple[Identifier, identifier] | Node ]: ... def __contains__(self, triple: Any) -> bool: ... def __add__(self, other: Any) -> Graph: ... def set(self, triple: Any) -> None: ... def subjects( self, predicate: Any | None = ..., object: Any | None = ... ) -> Iterable[Node]: ... def predicates( self, subject: Any | None = ..., object: Any | None = ... ) -> Iterable[Node]: ... def objects( self, subject: Any | None = ..., predicate: Any | None = ... ) -> Iterable[Identifier]: ... def subject_predicates(self, object: Any | None = ...) -> None: ... def subject_objects(self, predicate: Any | None = ...) -> None: ... def predicate_objects(self, subject: Any | None = ...) -> None: ... def triples_choices(self, triple: Any, context: Any | None = ...) -> None: ... def value( self, subject: Any | None = ..., predicate: Any = ..., object: Any | None = ..., default: Any | None = ..., any: bool = ..., ) -> Any: ... def label(self, subject: Any, default: str = ...) -> Any: ... def preferredLabel( self, subject: Any, lang: Any | None = ..., default: Any | None = ..., labelProperties: Any = ..., ) -> list[tuple[Any, Any]]: ... def comment(self, subject: Any, default: str = ...) -> Any: ... def items(self, list: Any) -> Iterator[Any]: ... def transitiveClosure( self, func: Any, arg: Any, seen: Any | None = ... ) -> Iterator[Any]: ... def transitive_objects( self, subject: Any, property: Any, remember: Any | None = ... ) -> Iterator[Any]: ... def transitive_subjects( self, predicate: Any, object: Any, remember: Any | None = ... ) -> Iterator[Any]: ... def seq(self, subject: Any) -> Seq | None: ... def qname(self, uri: Any) -> Any: ... def compute_qname(self, uri: Any, generate: bool = ...) -> Any: ... def bind( self, prefix: Any, namespace: Any, override: bool = ..., replace: bool = ... ) -> Any: ... def namespaces(self) -> Iterator[tuple[Any, Any]]: ... def absolutize(self, uri: Any, defrag: int = ...) -> Any: ... # no destination and non-None positional encoding @overload def serialize( self, destination: None, format: str, base: str | None, encoding: str, **args: Any, ) -> bytes: ... # no destination and non-None keyword encoding @overload def serialize( self, destination: None = ..., format: str = ..., base: str | None = ..., *, encoding: str, **args: Any, ) -> bytes: ... # no destination and None encoding @overload def serialize( self, destination: None = ..., format: str = ..., base: str | None = ..., encoding: None = ..., **args: Any, ) -> str: ... # non-None destination @overload def serialize( self, destination: str | pathlib.PurePath | IO[bytes], format: str = ..., base: str | None = ..., encoding: str | None = ..., **args: Any, ) -> "Graph": ... # fallback @overload def serialize( self, destination: str | pathlib.PurePath | IO[bytes] | None = ..., format: str = ..., base: str | None = ..., encoding: str | None = ..., **args: Any, ) -> Union[bytes, str, "Graph"]: ... def parse( self, source: Any | None = ..., publicID: Any | None = ..., format: str | None = ..., location: Any | None = ..., file: Any | None = ..., data: Any | None = ..., **args: Any, ) -> "Graph": ... def load( self, source: Any, publicID: Any | None = ..., format: str = ... ) -> "Graph": ... def query( self, query_object: Any, processor: str = ..., result: str = ..., initNs: Any | None = ..., initBindings: Any | None = ..., use_store_provided: bool = ..., **kwargs: Any, ) -> query.Result: ... def update( self, update_object: Any, processor: str = ..., initNs: Any | None = ..., initBindings: Any | None = ..., use_store_provided: bool = ..., **kwargs: Any, ) -> Any: ... def n3(self) -> str: ... def isomorphic(self, other: Any) -> bool: ... def connected(self) -> bool: ... def all_nodes(self) -> _set[Node]: ... def collection(self, identifier: Any) -> Collection: ... def resource(self, identifier: Any) -> Resource: ... def skolemize( self, new_graph: Any | None = ..., bnode: Any | None = ..., authority: Any | None = ..., basepath: Any | None = ..., ) -> Graph: ... def de_skolemize( self, new_graph: Any | None = ..., uriref: Any | None = ... ) -> Graph: ... class ConjunctiveGraph(Graph): context_aware: bool = ... default_union: bool = ... default_context: Any = ... def __init__( self, store: str = ..., identifier: Any | None = ..., default_graph_base: Any | None = ..., ) -> None: ... def add(self, triple_or_quad: Any) -> None: ... def addN(self, quads: Any) -> None: ... def remove(self, triple_or_quad: Any) -> None: ... # def triples(self, triple_or_quad: Tuple[Optional[Union[str, BNode]], Optional[Union[str, BNode]], Optional[BNode]], context: Tuple[Optional[Union[str, BNode]], Optional[Union[str, BNode]], Optional[BNode]]) -> Iterator[Tuple[Identifier, Identifier, Identifier]]: ... def quads(self, triple_or_quad: Any | None = ...) -> None: ... def triples_choices(self, triple: Any, context: Any | None = ...) -> None: ... def contexts(self, triple: Any | None = ...) -> None: ... def get_context( self, identifier: Node | str | None, quoted: bool = ..., base: str | None = ..., ) -> Graph: ... def remove_context(self, context: Any) -> None: ... def context_id(self, uri: Any, context_id: Any | None = ...) -> Any: ... def parse( self, source: Any | None = ..., publicID: Any | None = ..., format: str | None = ..., location: Any | None = ..., file: Any | None = ..., data: Any | None = ..., **args: Any, ) -> Graph: ... class Seq: def __init__(self, graph: Graph, subject: Any) -> None: ... def toPython(self) -> Seq: ... cwl_utils-0.41/mypy-stubs/rdflib/parser.pyi0000644000000000000000000000020313615410400015773 0ustar00from typing import Any class Parser: def __init__(self) -> None: ... def parse(self, source: Any, sink: Any) -> None: ... cwl_utils-0.41/mypy-stubs/rdflib/paths.pyi0000644000000000000000000000132413615410400015623 0ustar00from collections.abc import Callable, Generator from typing import Any, Union from rdflib.term import Node as Node from rdflib.term import URIRef as URIRef ZeroOrMore: str OneOrMore: str ZeroOrOne: str class Path: __or__: Callable[[Path, Union["URIRef", "Path"]], "AlternativePath"] __invert__: Callable[[Path], "InvPath"] __neg__: Callable[[Path], "NegatedPath"] __truediv__: Callable[[Path, Union["URIRef", "Path"]], "SequencePath"] __mul__: Callable[[Path, str], "MulPath"] def __hash__(self) -> int: ... def __lt__(self, other: Any) -> bool: ... class InvPath(Path): ... class SequencePath(Path): ... class AlternativePath(Path): ... class MulPath(Path): ... class NegatedPath(Path): ... cwl_utils-0.41/mypy-stubs/rdflib/plugin.pyi0000644000000000000000000000050513615410400016002 0ustar00from typing import Any, Type, TypeVar from rdflib.exceptions import Error def register(name: str, kind: Any, module_path: str, class_name: str) -> None: ... PluginT = TypeVar("PluginT") def get(name: str, kind: type[PluginT]) -> type[PluginT]: ... def plugins(name: Any | None = ..., kind: Any | None = ...) -> None: ... cwl_utils-0.41/mypy-stubs/rdflib/query.pyi0000644000000000000000000000250513615410400015653 0ustar00from collections.abc import Iterator, Mapping from typing import IO, Any, Dict, List, Optional, SupportsIndex, Tuple, overload from rdflib import URIRef, Variable from rdflib.term import Identifier class ResultRow(tuple["Identifier", ...]): def __new__( cls, values: Mapping[Variable, Identifier], labels: list[Variable] ) -> ResultRow: ... def __getattr__(self, name: str) -> Identifier: ... @overload def __getitem__(self, name: str) -> Identifier: ... @overload def __getitem__(self, __x: SupportsIndex) -> Identifier: ... @overload def __getitem__(self, __x: slice) -> tuple[Identifier, ...]: ... def get(self, name: str, default: Any | None = ...) -> Identifier: ... def asdict(self) -> dict[str, Identifier]: ... class Result: type: Any vars: Any askAnswer: Any graph: Any def __init__(self, type_: str) -> None: ... bindings: Any def __iter__(self) -> Iterator[bool | ResultRow]: ... @staticmethod def parse( source: IO[Any] | None = ..., format: str | None = ..., content_type: str | None = ..., **kwargs: Any, ) -> Result: ... def serialize( self, destination: str | IO[Any] | None = ..., encoding: str = ..., format: str = ..., **args: Any, ) -> bytes | None: ... cwl_utils-0.41/mypy-stubs/rdflib/resource.pyi0000644000000000000000000000262113615410400016334 0ustar00from collections.abc import Iterable, Iterator from typing import Any, Tuple from _typeshed import Incomplete from rdflib.graph import Graph, Seq from rdflib.term import Node class Resource: def __init__(self, graph: Graph, subject: Node) -> None: ... graph: Incomplete identifier: Incomplete def add(self, p: Node, o: Node) -> None: ... def remove(self, p: Node, o: Node | None = ...) -> None: ... def set(self, p: Node, o: Node) -> None: ... def subjects(self, predicate: Any | None = ...) -> Iterable[Node]: ... def predicates(self, o: Incomplete | None = ...) -> Iterable[Node]: ... def objects(self, predicate: Any | None = ...) -> Iterable[Node]: ... def subject_predicates(self) -> Iterator[tuple[Node, Node]]: ... def subject_objects(self) -> Iterator[tuple[Node, Node]]: ... def predicate_objects(self) -> Iterator[tuple[Node, Node]]: ... def value( self, p: Node, o: Node | None = ..., default: Any | None = ..., any: bool = ... ) -> Any: ... def label(self) -> Any: ... def comment(self) -> Any: ... def items(self) -> Iterator[Any]: ... def transitive_objects( self, predicate: Node, remember: Any | None = ... ) -> Iterator[Any]: ... def transitive_subjects( self, predicate: Node, remember: Any | None = ... ) -> Iterator[Any]: ... def seq(self) -> Seq | None: ... def qname(self) -> Any: ... cwl_utils-0.41/mypy-stubs/rdflib/term.pyi0000644000000000000000000000251713615410400015460 0ustar00from collections.abc import Callable from typing import Any, Union class Node: ... class Identifier(Node, str): def __new__(cls, value: Any | str | None) -> "Identifier": ... def eq(self, other: Any) -> bool: ... def neq(self, other: Any) -> bool: ... class IdentifiedNode(Identifier): ... class URIRef(IdentifiedNode): def toPython(self) -> str: ... def n3(self, namespace_manager: Any | None = ...) -> str: ... def defrag(self) -> "URIRef": ... def de_skolemize(self) -> "BNode": ... class Genid(URIRef): ... class RDFLibGenid(Genid): ... class BNode(IdentifiedNode): def toPython(self) -> str: ... def n3(self, namespace_manager: Any | None = ...) -> str: ... def skolemize( self, authority: Any | None = ..., basepath: Any | None = ... ) -> "RDFLibGenid": ... class Literal(Identifier): def normalize(self) -> "Literal": ... @property def value(self) -> Any: ... @property def language(self) -> str | None: ... @property def datatype(self) -> Any: ... def eq(self, other: Any) -> bool: ... def neq(self, other: Any) -> bool: ... def n3(self, namespace_manager: Any | None = ...) -> str: ... def toPython(self) -> str: ... class Variable(Identifier): def toPython(self) -> str: ... def n3(self, namespace_manager: Any | None = ...) -> str: ... cwl_utils-0.41/mypy-stubs/rdflib/namespace/_CSVW.pyi0000644000000000000000000000373213615410400017366 0ustar00from rdflib.namespace import DefinedNamespace as DefinedNamespace from rdflib.namespace import Namespace as Namespace from rdflib.term import URIRef as URIRef class CSVW(DefinedNamespace): aboutUrl: URIRef base: URIRef column: URIRef columnReference: URIRef commentPrefix: URIRef datatype: URIRef decimalChar: URIRef default: URIRef delimiter: URIRef describes: URIRef dialect: URIRef doubleQuote: URIRef encoding: URIRef foreignKey: URIRef format: URIRef groupChar: URIRef header: URIRef headerRowCount: URIRef lang: URIRef length: URIRef lineTerminators: URIRef maxExclusive: URIRef maxInclusive: URIRef maxLength: URIRef minExclusive: URIRef minInclusive: URIRef minLength: URIRef name: URIRef note: URIRef null: URIRef ordered: URIRef pattern: URIRef primaryKey: URIRef propertyUrl: URIRef quoteChar: URIRef reference: URIRef referencedRow: URIRef required: URIRef resource: URIRef row: URIRef rowTitle: URIRef rownum: URIRef schemaReference: URIRef scriptFormat: URIRef separator: URIRef skipBlankRows: URIRef skipColumns: URIRef skipInitialSpace: URIRef skipRows: URIRef source: URIRef suppressOutput: URIRef table: URIRef tableDirection: URIRef tableSchema: URIRef targetFormat: URIRef textDirection: URIRef title: URIRef transformations: URIRef trim: URIRef url: URIRef valueUrl: URIRef virtual: URIRef Cell: URIRef Column: URIRef Datatype: URIRef Dialect: URIRef Direction: URIRef ForeignKey: URIRef NumericFormat: URIRef Row: URIRef Schema: URIRef Table: URIRef TableGroup: URIRef TableReference: URIRef Transformation: URIRef JSON: URIRef uriTemplate: URIRef auto: URIRef inherit: URIRef ltr: URIRef rtl: URIRef csvEncodedTabularData: URIRef tabularMetadata: URIRef cwl_utils-0.41/mypy-stubs/rdflib/namespace/_DC.pyi0000644000000000000000000000075513615410400017074 0ustar00from rdflib.namespace import DefinedNamespace as DefinedNamespace from rdflib.namespace import Namespace as Namespace from rdflib.term import URIRef as URIRef class DC(DefinedNamespace): contributor: URIRef coverage: URIRef creator: URIRef date: URIRef description: URIRef format: URIRef identifier: URIRef language: URIRef publisher: URIRef relation: URIRef rights: URIRef source: URIRef subject: URIRef title: URIRef type: URIRef cwl_utils-0.41/mypy-stubs/rdflib/namespace/_DCAT.pyi0000644000000000000000000000201213615410400017305 0ustar00from rdflib.namespace import DefinedNamespace as DefinedNamespace from rdflib.namespace import Namespace as Namespace from rdflib.term import URIRef as URIRef class DCAT(DefinedNamespace): accessURL: URIRef bbox: URIRef byteSize: URIRef centroid: URIRef compressFormat: URIRef contactPoint: URIRef dataset: URIRef distribution: URIRef downloadURL: URIRef endDate: URIRef keyword: URIRef landingPage: URIRef mediaType: URIRef packageFormat: URIRef record: URIRef startDate: URIRef theme: URIRef themeTaxonomy: URIRef Catalog: URIRef CatalogRecord: URIRef Dataset: URIRef Distribution: URIRef DataService: URIRef Relationship: URIRef Resource: URIRef Role: URIRef spatialResolutionInMeters: URIRef temporalResolution: URIRef accessService: URIRef catalog: URIRef endpointDescription: URIRef endpointURL: URIRef hadRole: URIRef qualifiedRelation: URIRef servesDataset: URIRef service: URIRef cwl_utils-0.41/mypy-stubs/rdflib/namespace/_DCTERMS.pyi0000644000000000000000000000447113615410400017706 0ustar00from rdflib.namespace import DefinedNamespace as DefinedNamespace from rdflib.namespace import Namespace as Namespace from rdflib.term import URIRef as URIRef class DCTERMS(DefinedNamespace): DCMIType: URIRef DDC: URIRef IMT: URIRef LCC: URIRef LCSH: URIRef MESH: URIRef NLM: URIRef TGN: URIRef UDC: URIRef abstract: URIRef accessRights: URIRef accrualMethod: URIRef accrualPeriodicity: URIRef accrualPolicy: URIRef alternative: URIRef audience: URIRef available: URIRef bibliographicCitation: URIRef conformsTo: URIRef contributor: URIRef coverage: URIRef created: URIRef creator: URIRef date: URIRef dateAccepted: URIRef dateCopyrighted: URIRef dateSubmitted: URIRef description: URIRef educationLevel: URIRef extent: URIRef format: URIRef hasFormat: URIRef hasPart: URIRef hasVersion: URIRef identifier: URIRef instructionalMethod: URIRef isFormatOf: URIRef isPartOf: URIRef isReferencedBy: URIRef isReplacedBy: URIRef isRequiredBy: URIRef isVersionOf: URIRef issued: URIRef language: URIRef license: URIRef mediator: URIRef medium: URIRef modified: URIRef provenance: URIRef publisher: URIRef references: URIRef relation: URIRef replaces: URIRef requires: URIRef rights: URIRef rightsHolder: URIRef source: URIRef spatial: URIRef subject: URIRef tableOfContents: URIRef temporal: URIRef title: URIRef type: URIRef valid: URIRef Agent: URIRef AgentClass: URIRef BibliographicResource: URIRef FileFormat: URIRef Frequency: URIRef Jurisdiction: URIRef LicenseDocument: URIRef LinguisticSystem: URIRef Location: URIRef LocationPeriodOrJurisdiction: URIRef MediaType: URIRef MediaTypeOrExtent: URIRef MethodOfAccrual: URIRef MethodOfInstruction: URIRef PeriodOfTime: URIRef PhysicalMedium: URIRef PhysicalResource: URIRef Policy: URIRef ProvenanceStatement: URIRef RightsStatement: URIRef SizeOrDuration: URIRef Standard: URIRef Box: URIRef ISO3166: URIRef Period: URIRef Point: URIRef RFC1766: URIRef RFC3066: URIRef RFC4646: URIRef RFC5646: URIRef URI: URIRef W3CDTF: URIRef cwl_utils-0.41/mypy-stubs/rdflib/namespace/_DOAP.pyi0000644000000000000000000000212513615410400017322 0ustar00from rdflib.namespace import DefinedNamespace as DefinedNamespace from rdflib.namespace import Namespace as Namespace from rdflib.term import URIRef as URIRef class DOAP(DefinedNamespace): audience: URIRef blog: URIRef browse: URIRef category: URIRef created: URIRef description: URIRef developer: URIRef documenter: URIRef helper: URIRef implements: URIRef language: URIRef license: URIRef location: URIRef maintainer: URIRef module: URIRef name: URIRef os: URIRef platform: URIRef release: URIRef repository: URIRef repositoryOf: URIRef revision: URIRef screenshots: URIRef shortdesc: URIRef tester: URIRef translator: URIRef vendor: URIRef wiki: URIRef ArchRepository: URIRef BKRepository: URIRef BazaarBranch: URIRef CVSRepository: URIRef DarcsRepository: URIRef GitBranch: URIRef GitRepository: URIRef HgRepository: URIRef Project: URIRef Repository: URIRef SVNRepository: URIRef Specification: URIRef Version: URIRef homepage: URIRef cwl_utils-0.41/mypy-stubs/rdflib/namespace/_FOAF.pyi0000644000000000000000000000346713615410400017324 0ustar00from rdflib.namespace import DefinedNamespace as DefinedNamespace from rdflib.namespace import Namespace as Namespace from rdflib.term import URIRef as URIRef class FOAF(DefinedNamespace): account: URIRef accountName: URIRef accountServiceHomepage: URIRef age: URIRef based_near: URIRef birthday: URIRef currentProject: URIRef depiction: URIRef depicts: URIRef dnaChecksum: URIRef familyName: URIRef family_name: URIRef firstName: URIRef focus: URIRef fundedBy: URIRef geekcode: URIRef gender: URIRef givenName: URIRef givenname: URIRef holdsAccount: URIRef img: URIRef interest: URIRef knows: URIRef lastName: URIRef made: URIRef maker: URIRef member: URIRef membershipClass: URIRef myersBriggs: URIRef name: URIRef nick: URIRef page: URIRef pastProject: URIRef phone: URIRef plan: URIRef primaryTopic: URIRef publications: URIRef schoolHomepage: URIRef sha1: URIRef skypeID: URIRef status: URIRef surname: URIRef theme: URIRef thumbnail: URIRef tipjar: URIRef title: URIRef topic: URIRef topic_interest: URIRef workInfoHomepage: URIRef workplaceHomepage: URIRef Agent: URIRef Document: URIRef Group: URIRef Image: URIRef LabelProperty: URIRef OnlineAccount: URIRef OnlineChatAccount: URIRef OnlineEcommerceAccount: URIRef OnlineGamingAccount: URIRef Organization: URIRef Person: URIRef PersonalProfileDocument: URIRef Project: URIRef aimChatID: URIRef homepage: URIRef icqChatID: URIRef isPrimaryTopicOf: URIRef jabberID: URIRef logo: URIRef mbox: URIRef mbox_sha1sum: URIRef msnChatID: URIRef openid: URIRef weblog: URIRef yahooChatID: URIRef cwl_utils-0.41/mypy-stubs/rdflib/namespace/_ODRL2.pyi0000644000000000000000000001112313615410400017417 0ustar00from rdflib.namespace import DefinedNamespace as DefinedNamespace from rdflib.namespace import Namespace as Namespace from rdflib.term import URIRef as URIRef class ODRL2(DefinedNamespace): action: URIRef andSequence: URIRef assignee: URIRef assigneeOf: URIRef assigner: URIRef assignerOf: URIRef attributedParty: URIRef attributingParty: URIRef compensatedParty: URIRef compensatingParty: URIRef conflict: URIRef consentedParty: URIRef consentingParty: URIRef consequence: URIRef constraint: URIRef contractedParty: URIRef contractingParty: URIRef dataType: URIRef duty: URIRef failure: URIRef function: URIRef hasPolicy: URIRef implies: URIRef includedIn: URIRef informedParty: URIRef informingParty: URIRef inheritAllowed: URIRef inheritFrom: URIRef inheritRelation: URIRef leftOperand: URIRef obligation: URIRef operand: URIRef operator: URIRef output: URIRef partOf: URIRef payeeParty: URIRef permission: URIRef profile: URIRef prohibition: URIRef proximity: URIRef refinement: URIRef relation: URIRef remedy: URIRef rightOperand: URIRef rightOperandReference: URIRef scope: URIRef source: URIRef status: URIRef target: URIRef timedCount: URIRef trackedParty: URIRef trackingParty: URIRef uid: URIRef undefined: URIRef unit: URIRef xone: URIRef All: URIRef All2ndConnections: URIRef AllConnections: URIRef AllGroups: URIRef Group: URIRef Individual: URIRef absolutePosition: URIRef absoluteSize: URIRef absoluteSpatialPosition: URIRef absoluteTemporalPosition: URIRef count: URIRef dateTime: URIRef delayPeriod: URIRef deliveryChannel: URIRef device: URIRef elapsedTime: URIRef eq: URIRef event: URIRef fileFormat: URIRef gt: URIRef gteq: URIRef hasPart: URIRef ignore: URIRef industry: URIRef invalid: URIRef isA: URIRef isAllOf: URIRef isAnyOf: URIRef isNoneOf: URIRef isPartOf: URIRef language: URIRef lt: URIRef lteq: URIRef media: URIRef meteredTime: URIRef neq: URIRef payAmount: URIRef percentage: URIRef perm: URIRef policyUsage: URIRef product: URIRef prohibit: URIRef purpose: URIRef recipient: URIRef relativePosition: URIRef relativeSize: URIRef relativeSpatialPosition: URIRef relativeTemporalPosition: URIRef resolution: URIRef spatial: URIRef spatialCoordinates: URIRef support: URIRef system: URIRef systemDevice: URIRef timeInterval: URIRef unitOfCount: URIRef version: URIRef virtualLocation: URIRef Action: URIRef Agreement: URIRef Assertion: URIRef Asset: URIRef AssetCollection: URIRef AssetScope: URIRef ConflictTerm: URIRef Constraint: URIRef Duty: URIRef LeftOperand: URIRef LogicalConstraint: URIRef Offer: URIRef Operator: URIRef Party: URIRef PartyCollection: URIRef PartyScope: URIRef Permission: URIRef Policy: URIRef Privacy: URIRef Prohibition: URIRef Request: URIRef RightOperand: URIRef Rule: URIRef Set: URIRef Ticket: URIRef UndefinedTerm: URIRef acceptTracking: URIRef adHocShare: URIRef aggregate: URIRef annotate: URIRef anonymize: URIRef append: URIRef appendTo: URIRef archive: URIRef attachPolicy: URIRef attachSource: URIRef attribute: URIRef commercialize: URIRef compensate: URIRef concurrentUse: URIRef copy: URIRef core: URIRef delete: URIRef derive: URIRef digitize: URIRef display: URIRef distribute: URIRef ensureExclusivity: URIRef execute: URIRef export: URIRef extract: URIRef extractChar: URIRef extractPage: URIRef extractWord: URIRef give: URIRef grantUse: URIRef include: URIRef index: URIRef inform: URIRef install: URIRef lease: URIRef lend: URIRef license: URIRef modify: URIRef move: URIRef nextPolicy: URIRef obtainConsent: URIRef pay: URIRef play: URIRef present: URIRef preview: URIRef print: URIRef read: URIRef reproduce: URIRef reviewPolicy: URIRef secondaryUse: URIRef sell: URIRef share: URIRef shareAlike: URIRef stream: URIRef synchronize: URIRef textToSpeech: URIRef transfer: URIRef transform: URIRef translate: URIRef uninstall: URIRef use: URIRef watermark: URIRef write: URIRef writeTo: URIRef cwl_utils-0.41/mypy-stubs/rdflib/namespace/_ORG.pyi0000644000000000000000000000235313615410400017231 0ustar00from rdflib.namespace import DefinedNamespace as DefinedNamespace from rdflib.namespace import Namespace as Namespace from rdflib.term import URIRef as URIRef class ORG(DefinedNamespace): basedAt: URIRef changedBy: URIRef classification: URIRef hasMember: URIRef hasMembership: URIRef hasPost: URIRef hasPrimarySite: URIRef hasRegisteredSite: URIRef hasSite: URIRef hasSubOrganization: URIRef hasUnit: URIRef headOf: URIRef heldBy: URIRef holds: URIRef identifier: URIRef linkedTo: URIRef location: URIRef member: URIRef memberDuring: URIRef memberOf: URIRef organization: URIRef originalOrganization: URIRef postIn: URIRef purpose: URIRef remuneration: URIRef reportsTo: URIRef resultedFrom: URIRef resultingOrganization: URIRef role: URIRef roleProperty: URIRef siteAddress: URIRef siteOf: URIRef subOrganizationOf: URIRef transitiveSubOrganizationOf: URIRef unitOf: URIRef ChangeEvent: URIRef FormalOrganization: URIRef Membership: URIRef Organization: URIRef OrganizationalCollaboration: URIRef OrganizationalUnit: URIRef Post: URIRef Role: URIRef Site: URIRef Head: URIRef cwl_utils-0.41/mypy-stubs/rdflib/namespace/_OWL.pyi0000644000000000000000000000432413615410400017243 0ustar00from rdflib.namespace import DefinedNamespace as DefinedNamespace from rdflib.namespace import Namespace as Namespace from rdflib.term import URIRef as URIRef class OWL(DefinedNamespace): allValuesFrom: URIRef annotatedProperty: URIRef annotatedSource: URIRef annotatedTarget: URIRef assertionProperty: URIRef cardinality: URIRef complementOf: URIRef datatypeComplementOf: URIRef differentFrom: URIRef disjointUnionOf: URIRef disjointWith: URIRef distinctMembers: URIRef equivalentClass: URIRef equivalentProperty: URIRef hasKey: URIRef hasSelf: URIRef hasValue: URIRef intersectionOf: URIRef inverseOf: URIRef maxCardinality: URIRef maxQualifiedCardinality: URIRef members: URIRef minCardinality: URIRef minQualifiedCardinality: URIRef onClass: URIRef onDataRange: URIRef onDatatype: URIRef onProperties: URIRef onProperty: URIRef oneOf: URIRef propertyChainAxiom: URIRef propertyDisjointWith: URIRef qualifiedCardinality: URIRef sameAs: URIRef someValuesFrom: URIRef sourceIndividual: URIRef targetIndividual: URIRef targetValue: URIRef unionOf: URIRef withRestrictions: URIRef AllDifferent: URIRef AllDisjointClasses: URIRef AllDisjointProperties: URIRef Annotation: URIRef AnnotationProperty: URIRef AsymmetricProperty: URIRef Axiom: URIRef Class: URIRef DataRange: URIRef DatatypeProperty: URIRef DeprecatedClass: URIRef DeprecatedProperty: URIRef FunctionalProperty: URIRef InverseFunctionalProperty: URIRef IrreflexiveProperty: URIRef NamedIndividual: URIRef NegativePropertyAssertion: URIRef ObjectProperty: URIRef Ontology: URIRef OntologyProperty: URIRef ReflexiveProperty: URIRef Restriction: URIRef SymmetricProperty: URIRef TransitiveProperty: URIRef backwardCompatibleWith: URIRef deprecated: URIRef incompatibleWith: URIRef priorVersion: URIRef versionInfo: URIRef Nothing: URIRef Thing: URIRef bottomDataProperty: URIRef topDataProperty: URIRef bottomObjectProperty: URIRef topObjectProperty: URIRef imports: URIRef versionIRI: URIRef cwl_utils-0.41/mypy-stubs/rdflib/namespace/_PROF.pyi0000644000000000000000000000067113615410400017351 0ustar00from rdflib.namespace import DefinedNamespace as DefinedNamespace from rdflib.namespace import Namespace as Namespace from rdflib.term import URIRef as URIRef class PROF(DefinedNamespace): Profile: URIRef ResourceDescriptor: URIRef ResourceRole: URIRef hasToken: URIRef hasArtifact: URIRef hasResource: URIRef hasRole: URIRef isInheritedFrom: URIRef isProfileOf: URIRef isTransitiveProfileOf: URIRef cwl_utils-0.41/mypy-stubs/rdflib/namespace/_PROV.pyi0000644000000000000000000001065013615410400017367 0ustar00from rdflib.namespace import DefinedNamespace as DefinedNamespace from rdflib.namespace import Namespace as Namespace from rdflib.term import URIRef as URIRef class PROV(DefinedNamespace): activityOfInfluence: URIRef agentOfInfluence: URIRef contributed: URIRef ended: URIRef entityOfInfluence: URIRef generalizationOf: URIRef generatedAsDerivation: URIRef hadDelegate: URIRef hadDerivation: URIRef hadInfluence: URIRef hadRevision: URIRef informed: URIRef locationOf: URIRef qualifiedAssociationOf: URIRef qualifiedAttributionOf: URIRef qualifiedCommunicationOf: URIRef qualifiedDelegationOf: URIRef qualifiedDerivationOf: URIRef qualifiedEndOf: URIRef qualifiedGenerationOf: URIRef qualifiedInfluenceOf: URIRef qualifiedInvalidationOf: URIRef qualifiedQuotationOf: URIRef qualifiedSourceOf: URIRef qualifiedStartOf: URIRef qualifiedUsingActivity: URIRef quotedAs: URIRef revisedEntity: URIRef started: URIRef wasActivityOfInfluence: URIRef wasAssociateFor: URIRef wasMemberOf: URIRef wasPlanOf: URIRef wasPrimarySourceOf: URIRef wasRoleIn: URIRef wasUsedBy: URIRef wasUsedInDerivation: URIRef aq: URIRef category: URIRef component: URIRef constraints: URIRef definition: URIRef dm: URIRef editorialNote: URIRef editorsDefinition: URIRef inverse: URIRef n: URIRef order: URIRef qualifiedForm: URIRef sharesDefinitionWith: URIRef specializationOf: URIRef todo: URIRef unqualifiedForm: URIRef wasRevisionOf: URIRef Accept: URIRef Activity: URIRef ActivityInfluence: URIRef Agent: URIRef AgentInfluence: URIRef Association: URIRef Attribution: URIRef Bundle: URIRef Collection: URIRef Communication: URIRef Contribute: URIRef Contributor: URIRef Copyright: URIRef Create: URIRef Creator: URIRef Delegation: URIRef Derivation: URIRef Dictionary: URIRef DirectQueryService: URIRef EmptyDictionary: URIRef End: URIRef Entity: URIRef EntityInfluence: URIRef Generation: URIRef Influence: URIRef Insertion: URIRef InstantaneousEvent: URIRef Invalidation: URIRef KeyEntityPair: URIRef Location: URIRef Modify: URIRef Organization: URIRef Person: URIRef Plan: URIRef PrimarySource: URIRef Publish: URIRef Publisher: URIRef Quotation: URIRef Removal: URIRef Replace: URIRef Revision: URIRef RightsAssignment: URIRef RightsHolder: URIRef Role: URIRef ServiceDescription: URIRef SoftwareAgent: URIRef Start: URIRef Submit: URIRef Usage: URIRef atTime: URIRef endedAtTime: URIRef generatedAtTime: URIRef invalidatedAtTime: URIRef provenanceUriTemplate: URIRef removedKey: URIRef startedAtTime: URIRef value: URIRef pairEntity: URIRef pairKey: URIRef EmptyCollection: URIRef actedOnBehalfOf: URIRef activity: URIRef agent: URIRef alternateOf: URIRef asInBundle: URIRef atLocation: URIRef derivedByInsertionFrom: URIRef derivedByRemovalFrom: URIRef describesService: URIRef dictionary: URIRef entity: URIRef generated: URIRef hadActivity: URIRef hadDictionaryMember: URIRef hadGeneration: URIRef hadMember: URIRef hadPlan: URIRef hadPrimarySource: URIRef hadRole: URIRef hadUsage: URIRef has_anchor: URIRef has_provenance: URIRef has_query_service: URIRef influenced: URIRef influencer: URIRef insertedKeyEntityPair: URIRef invalidated: URIRef mentionOf: URIRef pingback: URIRef qualifiedAssociation: URIRef qualifiedAttribution: URIRef qualifiedCommunication: URIRef qualifiedDelegation: URIRef qualifiedDerivation: URIRef qualifiedEnd: URIRef qualifiedGeneration: URIRef qualifiedInfluence: URIRef qualifiedInsertion: URIRef qualifiedInvalidation: URIRef qualifiedPrimarySource: URIRef qualifiedQuotation: URIRef qualifiedRemoval: URIRef qualifiedRevision: URIRef qualifiedStart: URIRef qualifiedUsage: URIRef used: URIRef wasAssociatedWith: URIRef wasAttributedTo: URIRef wasDerivedFrom: URIRef wasEndedBy: URIRef wasGeneratedBy: URIRef wasInfluencedBy: URIRef wasInformedBy: URIRef wasInvalidatedBy: URIRef wasQuotedFrom: URIRef wasStartedBy: URIRef cwl_utils-0.41/mypy-stubs/rdflib/namespace/_QB.pyi0000644000000000000000000000212113615410400017075 0ustar00from rdflib.namespace import DefinedNamespace as DefinedNamespace from rdflib.namespace import Namespace as Namespace from rdflib.term import URIRef as URIRef class QB(DefinedNamespace): attribute: URIRef codeList: URIRef component: URIRef componentAttachment: URIRef componentProperty: URIRef componentRequired: URIRef concept: URIRef dataSet: URIRef dimension: URIRef hierarchyRoot: URIRef measure: URIRef measureDimension: URIRef measureType: URIRef observation: URIRef observationGroup: URIRef order: URIRef parentChildProperty: URIRef slice: URIRef sliceKey: URIRef sliceStructure: URIRef structure: URIRef Attachable: URIRef AttributeProperty: URIRef CodedProperty: URIRef ComponentProperty: URIRef ComponentSet: URIRef ComponentSpecification: URIRef DataSet: URIRef DataStructureDefinition: URIRef DimensionProperty: URIRef HierarchicalCodeList: URIRef MeasureProperty: URIRef Observation: URIRef ObservationGroup: URIRef Slice: URIRef SliceKey: URIRef cwl_utils-0.41/mypy-stubs/rdflib/namespace/_RDF.pyi0000644000000000000000000000115413615410400017213 0ustar00from rdflib.namespace import DefinedNamespace as DefinedNamespace from rdflib.namespace import Namespace as Namespace from rdflib.term import URIRef as URIRef class RDF(DefinedNamespace): nil: URIRef direction: URIRef first: URIRef language: URIRef object: URIRef predicate: URIRef rest: URIRef subject: URIRef type: URIRef value: URIRef Alt: URIRef Bag: URIRef CompoundLiteral: URIRef List: URIRef Property: URIRef Seq: URIRef Statement: URIRef HTML: URIRef JSON: URIRef PlainLiteral: URIRef XMLLiteral: URIRef langString: URIRef cwl_utils-0.41/mypy-stubs/rdflib/namespace/_RDFS.pyi0000644000000000000000000000100713615410400017333 0ustar00from rdflib.namespace import DefinedNamespace as DefinedNamespace from rdflib.namespace import Namespace as Namespace from rdflib.term import URIRef as URIRef class RDFS(DefinedNamespace): comment: URIRef domain: URIRef isDefinedBy: URIRef label: URIRef member: URIRef range: URIRef seeAlso: URIRef subClassOf: URIRef subPropertyOf: URIRef Class: URIRef Container: URIRef ContainerMembershipProperty: URIRef Datatype: URIRef Literal: URIRef Resource: URIRef cwl_utils-0.41/mypy-stubs/rdflib/namespace/_SDO.pyi0000644000000000000000000012067113615410400017233 0ustar00from rdflib.namespace import DefinedNamespace as DefinedNamespace from rdflib.namespace import Namespace as Namespace from rdflib.term import URIRef as URIRef class SDO(DefinedNamespace): ActiveActionStatus: URIRef CompletedActionStatus: URIRef FailedActionStatus: URIRef PotentialActionStatus: URIRef Researcher: URIRef GroupBoardingPolicy: URIRef ZoneBoardingPolicy: URIRef AudiobookFormat: URIRef EBook: URIRef Hardcover: URIRef Paperback: URIRef HearingImpairedSupported: URIRef TollFree: URIRef Friday: URIRef Monday: URIRef PublicHolidays: URIRef Saturday: URIRef Sunday: URIRef Thursday: URIRef Tuesday: URIRef Wednesday: URIRef OnSitePickup: URIRef CommentPermission: URIRef ReadPermission: URIRef WritePermission: URIRef AllWheelDriveConfiguration: URIRef FourWheelDriveConfiguration: URIRef FrontWheelDriveConfiguration: URIRef RearWheelDriveConfiguration: URIRef EventCancelled: URIRef EventMovedOnline: URIRef EventPostponed: URIRef EventRescheduled: URIRef EventScheduled: URIRef CoOp: URIRef MultiPlayer: URIRef SinglePlayer: URIRef OfflinePermanently: URIRef OfflineTemporarily: URIRef Online: URIRef OnlineFull: URIRef Female: URIRef Male: URIRef Discontinued: URIRef InStock: URIRef InStoreOnly: URIRef LimitedAvailability: URIRef OnlineOnly: URIRef OutOfStock: URIRef PreOrder: URIRef PreSale: URIRef SoldOut: URIRef ItemListOrderAscending: URIRef ItemListOrderDescending: URIRef ItemListUnordered: URIRef ParkingMap: URIRef SeatingMap: URIRef TransitMap: URIRef VenueMap: URIRef CompilationAlbum: URIRef DJMixAlbum: URIRef DemoAlbum: URIRef LiveAlbum: URIRef MixtapeAlbum: URIRef RemixAlbum: URIRef SoundtrackAlbum: URIRef SpokenWordAlbum: URIRef StudioAlbum: URIRef AlbumRelease: URIRef BroadcastRelease: URIRef EPRelease: URIRef SingleRelease: URIRef CDFormat: URIRef CassetteFormat: URIRef DVDFormat: URIRef DigitalAudioTapeFormat: URIRef DigitalFormat: URIRef LaserDiscFormat: URIRef VinylFormat: URIRef DamagedCondition: URIRef NewCondition: URIRef RefurbishedCondition: URIRef UsedCondition: URIRef OrderCancelled: URIRef OrderDelivered: URIRef OrderInTransit: URIRef OrderPaymentDue: URIRef OrderPickupAvailable: URIRef OrderProblem: URIRef OrderProcessing: URIRef OrderReturned: URIRef PaymentAutomaticallyApplied: URIRef PaymentComplete: URIRef PaymentDeclined: URIRef PaymentDue: URIRef PaymentPastDue: URIRef ReservationCancelled: URIRef ReservationConfirmed: URIRef ReservationHold: URIRef ReservationPending: URIRef DiabeticDiet: URIRef GlutenFreeDiet: URIRef HalalDiet: URIRef HinduDiet: URIRef KosherDiet: URIRef LowCalorieDiet: URIRef LowFatDiet: URIRef LowLactoseDiet: URIRef LowSaltDiet: URIRef VeganDiet: URIRef VegetarianDiet: URIRef RsvpResponseMaybe: URIRef RsvpResponseNo: URIRef RsvpResponseYes: URIRef LeftHandDriving: URIRef RightHandDriving: URIRef about: URIRef acceptedAnswer: URIRef acceptedOffer: URIRef acceptedPaymentMethod: URIRef acceptsReservations: URIRef accessCode: URIRef accessMode: URIRef accessModeSufficient: URIRef accessibilityAPI: URIRef accessibilityControl: URIRef accessibilityFeature: URIRef accessibilityHazard: URIRef accessibilitySummary: URIRef accountId: URIRef accountablePerson: URIRef acquiredFrom: URIRef actionAccessibilityRequirement: URIRef actionApplication: URIRef actionOption: URIRef actionPlatform: URIRef actionStatus: URIRef actor: URIRef actors: URIRef addOn: URIRef additionalName: URIRef additionalNumberOfGuests: URIRef additionalProperty: URIRef additionalType: URIRef address: URIRef addressCountry: URIRef addressLocality: URIRef addressRegion: URIRef advanceBookingRequirement: URIRef affiliation: URIRef afterMedia: URIRef agent: URIRef aggregateRating: URIRef aircraft: URIRef album: URIRef albumProductionType: URIRef albumRelease: URIRef albumReleaseType: URIRef albums: URIRef alignmentType: URIRef alternateName: URIRef alternativeHeadline: URIRef alumni: URIRef alumniOf: URIRef amenityFeature: URIRef amount: URIRef amountOfThisGood: URIRef annualPercentageRate: URIRef answerCount: URIRef application: URIRef applicationCategory: URIRef applicationSubCategory: URIRef applicationSuite: URIRef appliesToDeliveryMethod: URIRef appliesToPaymentMethod: URIRef area: URIRef areaServed: URIRef arrivalAirport: URIRef arrivalBusStop: URIRef arrivalGate: URIRef arrivalPlatform: URIRef arrivalStation: URIRef arrivalTerminal: URIRef arrivalTime: URIRef artEdition: URIRef artMedium: URIRef artform: URIRef articleBody: URIRef articleSection: URIRef artworkSurface: URIRef assembly: URIRef assemblyVersion: URIRef associatedArticle: URIRef associatedMedia: URIRef athlete: URIRef attendee: URIRef attendees: URIRef audience: URIRef audienceType: URIRef audio: URIRef authenticator: URIRef author: URIRef availability: URIRef availabilityEnds: URIRef availabilityStarts: URIRef availableAtOrFrom: URIRef availableChannel: URIRef availableDeliveryMethod: URIRef availableFrom: URIRef availableLanguage: URIRef availableOnDevice: URIRef availableThrough: URIRef award: URIRef awards: URIRef awayTeam: URIRef baseSalary: URIRef bccRecipient: URIRef bed: URIRef beforeMedia: URIRef benefits: URIRef bestRating: URIRef billingAddress: URIRef billingIncrement: URIRef billingPeriod: URIRef birthDate: URIRef birthPlace: URIRef bitrate: URIRef blogPost: URIRef blogPosts: URIRef boardingGroup: URIRef boardingPolicy: URIRef bookEdition: URIRef bookFormat: URIRef bookingAgent: URIRef bookingTime: URIRef borrower: URIRef box: URIRef branchCode: URIRef branchOf: URIRef brand: URIRef breadcrumb: URIRef broadcastAffiliateOf: URIRef broadcastChannelId: URIRef broadcastDisplayName: URIRef broadcastFrequency: URIRef broadcastFrequencyValue: URIRef broadcastOfEvent: URIRef broadcastServiceTier: URIRef broadcastTimezone: URIRef broadcaster: URIRef broker: URIRef browserRequirements: URIRef busName: URIRef busNumber: URIRef businessFunction: URIRef buyer: URIRef byArtist: URIRef calories: URIRef candidate: URIRef caption: URIRef carbohydrateContent: URIRef cargoVolume: URIRef carrier: URIRef carrierRequirements: URIRef catalog: URIRef catalogNumber: URIRef category: URIRef ccRecipient: URIRef character: URIRef characterAttribute: URIRef characterName: URIRef cheatCode: URIRef checkinTime: URIRef checkoutTime: URIRef childMaxAge: URIRef childMinAge: URIRef children: URIRef cholesterolContent: URIRef circle: URIRef citation: URIRef claimReviewed: URIRef clipNumber: URIRef closes: URIRef coach: URIRef codeRepository: URIRef codeSampleType: URIRef colleague: URIRef colleagues: URIRef collection: URIRef color: URIRef comment: URIRef commentCount: URIRef commentText: URIRef commentTime: URIRef competitor: URIRef composer: URIRef confirmationNumber: URIRef contactOption: URIRef contactPoint: URIRef contactPoints: URIRef contactType: URIRef containedIn: URIRef containedInPlace: URIRef containsPlace: URIRef containsSeason: URIRef contentLocation: URIRef contentRating: URIRef contentSize: URIRef contentType: URIRef contentUrl: URIRef contributor: URIRef cookTime: URIRef cookingMethod: URIRef copyrightHolder: URIRef copyrightYear: URIRef countriesNotSupported: URIRef countriesSupported: URIRef countryOfOrigin: URIRef course: URIRef courseCode: URIRef courseMode: URIRef coursePrerequisites: URIRef coverageEndTime: URIRef coverageStartTime: URIRef creator: URIRef creditedTo: URIRef cssSelector: URIRef currenciesAccepted: URIRef currency: URIRef customer: URIRef dataFeedElement: URIRef dataset: URIRef datasetTimeInterval: URIRef dateCreated: URIRef dateDeleted: URIRef dateIssued: URIRef dateModified: URIRef datePosted: URIRef datePublished: URIRef dateRead: URIRef dateReceived: URIRef dateSent: URIRef dateVehicleFirstRegistered: URIRef dateline: URIRef dayOfWeek: URIRef deathDate: URIRef deathPlace: URIRef defaultValue: URIRef deliveryAddress: URIRef deliveryLeadTime: URIRef deliveryMethod: URIRef deliveryStatus: URIRef department: URIRef departureAirport: URIRef departureBusStop: URIRef departureGate: URIRef departurePlatform: URIRef departureStation: URIRef departureTerminal: URIRef departureTime: URIRef dependencies: URIRef depth: URIRef description: URIRef device: URIRef director: URIRef directors: URIRef disambiguatingDescription: URIRef discount: URIRef discountCode: URIRef discountCurrency: URIRef discusses: URIRef discussionUrl: URIRef dissolutionDate: URIRef distance: URIRef distribution: URIRef doorTime: URIRef downloadUrl: URIRef downvoteCount: URIRef driveWheelConfiguration: URIRef dropoffLocation: URIRef dropoffTime: URIRef duns: URIRef duration: URIRef durationOfWarranty: URIRef duringMedia: URIRef editor: URIRef educationalAlignment: URIRef educationalCredentialAwarded: URIRef educationalFramework: URIRef educationalRole: URIRef educationalUse: URIRef elevation: URIRef eligibleCustomerType: URIRef eligibleDuration: URIRef eligibleQuantity: URIRef eligibleRegion: URIRef eligibleTransactionVolume: URIRef email: URIRef embedUrl: URIRef employee: URIRef employees: URIRef employmentType: URIRef encodesCreativeWork: URIRef encoding: URIRef encodingFormat: URIRef encodingType: URIRef encodings: URIRef endDate: URIRef endTime: URIRef endorsee: URIRef entertainmentBusiness: URIRef episode: URIRef episodeNumber: URIRef episodes: URIRef equal: URIRef error: URIRef estimatedCost: URIRef estimatedFlightDuration: URIRef estimatedSalary: URIRef event: URIRef eventStatus: URIRef events: URIRef exampleOfWork: URIRef executableLibraryName: URIRef exerciseCourse: URIRef exifData: URIRef expectedArrivalFrom: URIRef expectedArrivalUntil: URIRef expectsAcceptanceOf: URIRef experienceRequirements: URIRef expires: URIRef familyName: URIRef fatContent: URIRef faxNumber: URIRef featureList: URIRef feesAndCommissionsSpecification: URIRef fiberContent: URIRef fileFormat: URIRef fileSize: URIRef firstPerformance: URIRef flightDistance: URIRef flightNumber: URIRef floorSize: URIRef followee: URIRef follows: URIRef foodEstablishment: URIRef foodEvent: URIRef founder: URIRef founders: URIRef foundingDate: URIRef foundingLocation: URIRef free: URIRef fromLocation: URIRef fuelConsumption: URIRef fuelEfficiency: URIRef fuelType: URIRef funder: URIRef game: URIRef gameItem: URIRef gameLocation: URIRef gamePlatform: URIRef gameServer: URIRef gameTip: URIRef genre: URIRef geo: URIRef geoContains: URIRef geoCoveredBy: URIRef geoCovers: URIRef geoCrosses: URIRef geoDisjoint: URIRef geoEquals: URIRef geoIntersects: URIRef geoMidpoint: URIRef geoOverlaps: URIRef geoRadius: URIRef geoTouches: URIRef geoWithin: URIRef geographicArea: URIRef givenName: URIRef globalLocationNumber: URIRef grantee: URIRef greater: URIRef greaterOrEqual: URIRef gtin12: URIRef gtin13: URIRef gtin14: URIRef gtin8: URIRef hasBroadcastChannel: URIRef hasCourseInstance: URIRef hasDeliveryMethod: URIRef hasDigitalDocumentPermission: URIRef hasMap: URIRef hasMenu: URIRef hasMenuItem: URIRef hasMenuSection: URIRef hasOccupation: URIRef hasOfferCatalog: URIRef hasPOS: URIRef hasPart: URIRef headline: URIRef height: URIRef highPrice: URIRef hiringOrganization: URIRef homeLocation: URIRef homeTeam: URIRef honorificPrefix: URIRef honorificSuffix: URIRef hostingOrganization: URIRef hoursAvailable: URIRef httpMethod: URIRef iataCode: URIRef icaoCode: URIRef identifier: URIRef illustrator: URIRef image: URIRef inAlbum: URIRef inBroadcastLineup: URIRef inLanguage: URIRef inPlaylist: URIRef incentiveCompensation: URIRef incentives: URIRef includedComposition: URIRef includedDataCatalog: URIRef includedInDataCatalog: URIRef includesObject: URIRef industry: URIRef ingredients: URIRef installUrl: URIRef instructor: URIRef instrument: URIRef interactionCount: URIRef interactionService: URIRef interactionStatistic: URIRef interactionType: URIRef interactivityType: URIRef interestRate: URIRef inventoryLevel: URIRef isAccessibleForFree: URIRef isAccessoryOrSparePartFor: URIRef isBasedOn: URIRef isBasedOnUrl: URIRef isConsumableFor: URIRef isFamilyFriendly: URIRef isGift: URIRef isLiveBroadcast: URIRef isPartOf: URIRef isRelatedTo: URIRef isSimilarTo: URIRef isVariantOf: URIRef isbn: URIRef isicV4: URIRef isrcCode: URIRef issn: URIRef issueNumber: URIRef issuedBy: URIRef issuedThrough: URIRef iswcCode: URIRef item: URIRef itemCondition: URIRef itemListElement: URIRef itemListOrder: URIRef itemOffered: URIRef itemReviewed: URIRef itemShipped: URIRef jobBenefits: URIRef jobLocation: URIRef keywords: URIRef knownVehicleDamages: URIRef knows: URIRef landlord: URIRef language: URIRef lastReviewed: URIRef latitude: URIRef learningResourceType: URIRef legalName: URIRef leiCode: URIRef lender: URIRef lesser: URIRef lesserOrEqual: URIRef license: URIRef line: URIRef liveBlogUpdate: URIRef loanTerm: URIRef location: URIRef locationCreated: URIRef lodgingUnitDescription: URIRef lodgingUnitType: URIRef logo: URIRef longitude: URIRef loser: URIRef lowPrice: URIRef lyricist: URIRef lyrics: URIRef mainContentOfPage: URIRef mainEntity: URIRef mainEntityOfPage: URIRef makesOffer: URIRef manufacturer: URIRef map: URIRef mapType: URIRef maps: URIRef material: URIRef maxPrice: URIRef maxValue: URIRef maximumAttendeeCapacity: URIRef mealService: URIRef median: URIRef member: URIRef memberOf: URIRef members: URIRef membershipNumber: URIRef memoryRequirements: URIRef mentions: URIRef menu: URIRef menuAddOn: URIRef merchant: URIRef messageAttachment: URIRef mileageFromOdometer: URIRef minPrice: URIRef minValue: URIRef minimumPaymentDue: URIRef model: URIRef modifiedTime: URIRef mpn: URIRef multipleValues: URIRef musicArrangement: URIRef musicBy: URIRef musicCompositionForm: URIRef musicGroupMember: URIRef musicReleaseFormat: URIRef musicalKey: URIRef naics: URIRef name: URIRef namedPosition: URIRef nationality: URIRef netWorth: URIRef nextItem: URIRef nonEqual: URIRef numAdults: URIRef numChildren: URIRef numTracks: URIRef numberOfAirbags: URIRef numberOfAxles: URIRef numberOfBeds: URIRef numberOfDoors: URIRef numberOfEmployees: URIRef numberOfEpisodes: URIRef numberOfForwardGears: URIRef numberOfItems: URIRef numberOfPages: URIRef numberOfPlayers: URIRef numberOfPreviousOwners: URIRef numberOfRooms: URIRef numberOfSeasons: URIRef numberedPosition: URIRef nutrition: URIRef object: URIRef occupancy: URIRef occupationLocation: URIRef offerCount: URIRef offeredBy: URIRef offers: URIRef openingHours: URIRef openingHoursSpecification: URIRef opens: URIRef operatingSystem: URIRef opponent: URIRef option: URIRef orderDate: URIRef orderDelivery: URIRef orderItemNumber: URIRef orderItemStatus: URIRef orderNumber: URIRef orderQuantity: URIRef orderStatus: URIRef orderedItem: URIRef organizer: URIRef originAddress: URIRef ownedFrom: URIRef ownedThrough: URIRef owns: URIRef pageEnd: URIRef pageStart: URIRef pagination: URIRef parent: URIRef parentItem: URIRef parentOrganization: URIRef parentService: URIRef parents: URIRef partOfEpisode: URIRef partOfInvoice: URIRef partOfOrder: URIRef partOfSeason: URIRef partOfSeries: URIRef partOfTVSeries: URIRef participant: URIRef partySize: URIRef passengerPriorityStatus: URIRef passengerSequenceNumber: URIRef paymentAccepted: URIRef paymentDue: URIRef paymentDueDate: URIRef paymentMethod: URIRef paymentMethodId: URIRef paymentStatus: URIRef paymentUrl: URIRef percentile10: URIRef percentile25: URIRef percentile75: URIRef percentile90: URIRef performTime: URIRef performer: URIRef performerIn: URIRef performers: URIRef permissionType: URIRef permissions: URIRef permitAudience: URIRef permittedUsage: URIRef petsAllowed: URIRef photo: URIRef photos: URIRef pickupLocation: URIRef pickupTime: URIRef playMode: URIRef playerType: URIRef playersOnline: URIRef polygon: URIRef position: URIRef postOfficeBoxNumber: URIRef postalCode: URIRef potentialAction: URIRef predecessorOf: URIRef prepTime: URIRef previousItem: URIRef previousStartDate: URIRef price: URIRef priceComponent: URIRef priceCurrency: URIRef priceRange: URIRef priceSpecification: URIRef priceType: URIRef priceValidUntil: URIRef primaryImageOfPage: URIRef printColumn: URIRef printEdition: URIRef printPage: URIRef printSection: URIRef processingTime: URIRef processorRequirements: URIRef producer: URIRef produces: URIRef productID: URIRef productSupported: URIRef productionCompany: URIRef productionDate: URIRef proficiencyLevel: URIRef programMembershipUsed: URIRef programName: URIRef programmingLanguage: URIRef programmingModel: URIRef propertyID: URIRef proteinContent: URIRef provider: URIRef providerMobility: URIRef providesBroadcastService: URIRef providesService: URIRef publicAccess: URIRef publication: URIRef publishedOn: URIRef publisher: URIRef publishingPrinciples: URIRef purchaseDate: URIRef query: URIRef quest: URIRef question: URIRef ratingCount: URIRef ratingValue: URIRef readonlyValue: URIRef realEstateAgent: URIRef recipe: URIRef recipeCategory: URIRef recipeCuisine: URIRef recipeIngredient: URIRef recipeInstructions: URIRef recipeYield: URIRef recipient: URIRef recordLabel: URIRef recordedAs: URIRef recordedAt: URIRef recordedIn: URIRef recordingOf: URIRef referenceQuantity: URIRef referencesOrder: URIRef regionsAllowed: URIRef relatedLink: URIRef relatedTo: URIRef releaseDate: URIRef releaseNotes: URIRef releaseOf: URIRef releasedEvent: URIRef relevantOccupation: URIRef remainingAttendeeCapacity: URIRef replacee: URIRef replacer: URIRef replyToUrl: URIRef reportNumber: URIRef representativeOfPage: URIRef requiredCollateral: URIRef requiredGender: URIRef requiredMaxAge: URIRef requiredMinAge: URIRef requiredQuantity: URIRef requirements: URIRef requiresSubscription: URIRef reservationFor: URIRef reservationId: URIRef reservationStatus: URIRef reservedTicket: URIRef responsibilities: URIRef result: URIRef resultComment: URIRef resultReview: URIRef review: URIRef reviewAspect: URIRef reviewBody: URIRef reviewCount: URIRef reviewRating: URIRef reviewedBy: URIRef reviews: URIRef roleName: URIRef rsvpResponse: URIRef runtime: URIRef runtimePlatform: URIRef salaryCurrency: URIRef sameAs: URIRef sampleType: URIRef saturatedFatContent: URIRef scheduledPaymentDate: URIRef scheduledTime: URIRef schemaVersion: URIRef screenCount: URIRef screenshot: URIRef season: URIRef seasonNumber: URIRef seasons: URIRef seatNumber: URIRef seatRow: URIRef seatSection: URIRef seatingType: URIRef securityScreening: URIRef seeks: URIRef seller: URIRef sender: URIRef serialNumber: URIRef serverStatus: URIRef servesCuisine: URIRef serviceArea: URIRef serviceAudience: URIRef serviceLocation: URIRef serviceOperator: URIRef serviceOutput: URIRef servicePhone: URIRef servicePostalAddress: URIRef serviceSmsNumber: URIRef serviceType: URIRef serviceUrl: URIRef servingSize: URIRef sharedContent: URIRef sibling: URIRef siblings: URIRef significantLink: URIRef significantLinks: URIRef skills: URIRef sku: URIRef slogan: URIRef smokingAllowed: URIRef sodiumContent: URIRef softwareAddOn: URIRef softwareHelp: URIRef softwareRequirements: URIRef softwareVersion: URIRef sourceOrganization: URIRef spatial: URIRef spatialCoverage: URIRef speakable: URIRef specialCommitments: URIRef specialOpeningHoursSpecification: URIRef specialty: URIRef sponsor: URIRef sportsActivityLocation: URIRef sportsEvent: URIRef sportsTeam: URIRef spouse: URIRef starRating: URIRef startDate: URIRef startTime: URIRef steeringPosition: URIRef step: URIRef stepValue: URIRef steps: URIRef storageRequirements: URIRef streetAddress: URIRef subEvent: URIRef subEvents: URIRef subOrganization: URIRef subReservation: URIRef subjectOf: URIRef successorOf: URIRef sugarContent: URIRef suggestedAnswer: URIRef suggestedGender: URIRef suggestedMaxAge: URIRef suggestedMinAge: URIRef suitableForDiet: URIRef superEvent: URIRef supply: URIRef supportingData: URIRef surface: URIRef target: URIRef targetCollection: URIRef targetDescription: URIRef targetName: URIRef targetPlatform: URIRef targetProduct: URIRef targetUrl: URIRef taxID: URIRef telephone: URIRef temporal: URIRef temporalCoverage: URIRef text: URIRef thumbnail: URIRef thumbnailUrl: URIRef tickerSymbol: URIRef ticketNumber: URIRef ticketToken: URIRef ticketedSeat: URIRef timeRequired: URIRef title: URIRef toLocation: URIRef toRecipient: URIRef tool: URIRef totalPaymentDue: URIRef totalPrice: URIRef totalTime: URIRef touristType: URIRef track: URIRef trackingNumber: URIRef trackingUrl: URIRef tracks: URIRef trailer: URIRef trainName: URIRef trainNumber: URIRef transFatContent: URIRef transcript: URIRef translator: URIRef typeOfBed: URIRef typeOfGood: URIRef typicalAgeRange: URIRef underName: URIRef unitCode: URIRef unitText: URIRef unsaturatedFatContent: URIRef uploadDate: URIRef upvoteCount: URIRef url: URIRef urlTemplate: URIRef userInteractionCount: URIRef validFor: URIRef validFrom: URIRef validIn: URIRef validThrough: URIRef validUntil: URIRef value: URIRef valueAddedTaxIncluded: URIRef valueMaxLength: URIRef valueMinLength: URIRef valueName: URIRef valuePattern: URIRef valueReference: URIRef valueRequired: URIRef vatID: URIRef vehicleConfiguration: URIRef vehicleEngine: URIRef vehicleIdentificationNumber: URIRef vehicleInteriorColor: URIRef vehicleInteriorType: URIRef vehicleModelDate: URIRef vehicleSeatingCapacity: URIRef vehicleTransmission: URIRef vendor: URIRef version: URIRef video: URIRef videoFormat: URIRef videoFrameSize: URIRef videoQuality: URIRef volumeNumber: URIRef warranty: URIRef warrantyPromise: URIRef warrantyScope: URIRef webCheckinTime: URIRef weight: URIRef width: URIRef winner: URIRef wordCount: URIRef workExample: URIRef workFeatured: URIRef workHours: URIRef workLocation: URIRef workPerformed: URIRef workPresented: URIRef worksFor: URIRef worstRating: URIRef xpath: URIRef yearlyRevenue: URIRef yearsInOperation: URIRef AMRadioChannel: URIRef APIReference: URIRef AboutPage: URIRef AcceptAction: URIRef Accommodation: URIRef AccountingService: URIRef AchieveAction: URIRef Action: URIRef ActionAccessSpecification: URIRef ActionStatusType: URIRef ActivateAction: URIRef AddAction: URIRef AdministrativeArea: URIRef AdultEntertainment: URIRef AggregateOffer: URIRef AggregateRating: URIRef AgreeAction: URIRef Airline: URIRef Airport: URIRef AlignmentObject: URIRef AllocateAction: URIRef AmusementPark: URIRef AnimalShelter: URIRef Answer: URIRef Apartment: URIRef ApartmentComplex: URIRef AppendAction: URIRef ApplyAction: URIRef Aquarium: URIRef ArriveAction: URIRef ArtGallery: URIRef Article: URIRef AskAction: URIRef AssessAction: URIRef AssignAction: URIRef Attorney: URIRef Audience: URIRef AudioObject: URIRef AuthorizeAction: URIRef AutoBodyShop: URIRef AutoDealer: URIRef AutoPartsStore: URIRef AutoRental: URIRef AutoRepair: URIRef AutoWash: URIRef AutomatedTeller: URIRef AutomotiveBusiness: URIRef Bakery: URIRef BankAccount: URIRef BankOrCreditUnion: URIRef BarOrPub: URIRef Barcode: URIRef Beach: URIRef BeautySalon: URIRef BedAndBreakfast: URIRef BedDetails: URIRef BedType: URIRef BefriendAction: URIRef BikeStore: URIRef Blog: URIRef BlogPosting: URIRef BoardingPolicyType: URIRef BodyOfWater: URIRef Book: URIRef BookFormatType: URIRef BookSeries: URIRef BookStore: URIRef BookmarkAction: URIRef Boolean: URIRef BorrowAction: URIRef BowlingAlley: URIRef Brand: URIRef BreadcrumbList: URIRef Brewery: URIRef Bridge: URIRef BroadcastChannel: URIRef BroadcastEvent: URIRef BroadcastFrequencySpecification: URIRef BroadcastService: URIRef BuddhistTemple: URIRef BusReservation: URIRef BusStation: URIRef BusStop: URIRef BusTrip: URIRef BusinessAudience: URIRef BusinessEntityType: URIRef BusinessEvent: URIRef BusinessFunction: URIRef BuyAction: URIRef CableOrSatelliteService: URIRef CafeOrCoffeeShop: URIRef Campground: URIRef CampingPitch: URIRef Canal: URIRef CancelAction: URIRef Car: URIRef Casino: URIRef CatholicChurch: URIRef Cemetery: URIRef CheckAction: URIRef CheckInAction: URIRef CheckOutAction: URIRef CheckoutPage: URIRef ChildCare: URIRef ChildrensEvent: URIRef ChooseAction: URIRef Church: URIRef City: URIRef CityHall: URIRef CivicStructure: URIRef ClaimReview: URIRef Clip: URIRef ClothingStore: URIRef Code: URIRef CollectionPage: URIRef CollegeOrUniversity: URIRef ComedyClub: URIRef ComedyEvent: URIRef Comment: URIRef CommentAction: URIRef CommunicateAction: URIRef CompoundPriceSpecification: URIRef ComputerLanguage: URIRef ComputerStore: URIRef ConfirmAction: URIRef ConsumeAction: URIRef ContactPage: URIRef ContactPoint: URIRef ContactPointOption: URIRef Continent: URIRef ControlAction: URIRef ConvenienceStore: URIRef Conversation: URIRef CookAction: URIRef Corporation: URIRef Country: URIRef Course: URIRef CourseInstance: URIRef Courthouse: URIRef CreateAction: URIRef CreativeWork: URIRef CreativeWorkSeason: URIRef CreativeWorkSeries: URIRef CreditCard: URIRef Crematorium: URIRef CurrencyConversionService: URIRef DanceEvent: URIRef DanceGroup: URIRef DataCatalog: URIRef DataDownload: URIRef DataFeed: URIRef DataFeedItem: URIRef DataType: URIRef Dataset: URIRef Date: URIRef DateTime: URIRef DatedMoneySpecification: URIRef DayOfWeek: URIRef DaySpa: URIRef DeactivateAction: URIRef DefenceEstablishment: URIRef DeleteAction: URIRef DeliveryChargeSpecification: URIRef DeliveryEvent: URIRef DeliveryMethod: URIRef Demand: URIRef Dentist: URIRef DepartAction: URIRef DepartmentStore: URIRef DepositAccount: URIRef DigitalDocument: URIRef DigitalDocumentPermission: URIRef DigitalDocumentPermissionType: URIRef DisagreeAction: URIRef DiscoverAction: URIRef DiscussionForumPosting: URIRef DislikeAction: URIRef Distance: URIRef Distillery: URIRef DonateAction: URIRef DownloadAction: URIRef DrawAction: URIRef DrinkAction: URIRef DriveWheelConfigurationValue: URIRef DryCleaningOrLaundry: URIRef Duration: URIRef EatAction: URIRef EducationEvent: URIRef EducationalAudience: URIRef EducationalOrganization: URIRef Electrician: URIRef ElectronicsStore: URIRef ElementarySchool: URIRef EmailMessage: URIRef Embassy: URIRef EmergencyService: URIRef EmployeeRole: URIRef EmployerAggregateRating: URIRef EmploymentAgency: URIRef EndorseAction: URIRef EndorsementRating: URIRef Energy: URIRef EngineSpecification: URIRef EntertainmentBusiness: URIRef EntryPoint: URIRef Enumeration: URIRef Episode: URIRef Event: URIRef EventReservation: URIRef EventStatusType: URIRef EventVenue: URIRef ExerciseAction: URIRef ExerciseGym: URIRef ExhibitionEvent: URIRef FAQPage: URIRef FMRadioChannel: URIRef FastFoodRestaurant: URIRef Festival: URIRef FilmAction: URIRef FinancialProduct: URIRef FinancialService: URIRef FindAction: URIRef FireStation: URIRef Flight: URIRef FlightReservation: URIRef Float: URIRef Florist: URIRef FollowAction: URIRef FoodEstablishment: URIRef FoodEstablishmentReservation: URIRef FoodEvent: URIRef FoodService: URIRef FurnitureStore: URIRef Game: URIRef GamePlayMode: URIRef GameServer: URIRef GameServerStatus: URIRef GardenStore: URIRef GasStation: URIRef GatedResidenceCommunity: URIRef GenderType: URIRef GeneralContractor: URIRef GeoCircle: URIRef GeoCoordinates: URIRef GeoShape: URIRef GiveAction: URIRef GolfCourse: URIRef GovernmentBuilding: URIRef GovernmentOffice: URIRef GovernmentOrganization: URIRef GovernmentPermit: URIRef GovernmentService: URIRef GroceryStore: URIRef HVACBusiness: URIRef HairSalon: URIRef HardwareStore: URIRef HealthAndBeautyBusiness: URIRef HealthClub: URIRef HighSchool: URIRef HinduTemple: URIRef HobbyShop: URIRef HomeAndConstructionBusiness: URIRef HomeGoodsStore: URIRef Hospital: URIRef Hostel: URIRef Hotel: URIRef HotelRoom: URIRef House: URIRef HousePainter: URIRef HowTo: URIRef HowToDirection: URIRef HowToItem: URIRef HowToSection: URIRef HowToStep: URIRef HowToSupply: URIRef HowToTip: URIRef HowToTool: URIRef IceCreamShop: URIRef IgnoreAction: URIRef ImageGallery: URIRef ImageObject: URIRef IndividualProduct: URIRef InformAction: URIRef InsertAction: URIRef InstallAction: URIRef InsuranceAgency: URIRef Intangible: URIRef Integer: URIRef InteractAction: URIRef InteractionCounter: URIRef InternetCafe: URIRef InvestmentOrDeposit: URIRef InviteAction: URIRef Invoice: URIRef ItemAvailability: URIRef ItemList: URIRef ItemListOrderType: URIRef ItemPage: URIRef JewelryStore: URIRef JobPosting: URIRef JoinAction: URIRef LakeBodyOfWater: URIRef Landform: URIRef LandmarksOrHistoricalBuildings: URIRef Language: URIRef LeaveAction: URIRef LegalService: URIRef LegislativeBuilding: URIRef LendAction: URIRef Library: URIRef LikeAction: URIRef LiquorStore: URIRef ListItem: URIRef ListenAction: URIRef LiteraryEvent: URIRef LiveBlogPosting: URIRef LoanOrCredit: URIRef LocalBusiness: URIRef LocationFeatureSpecification: URIRef LockerDelivery: URIRef Locksmith: URIRef LodgingBusiness: URIRef LodgingReservation: URIRef LoseAction: URIRef Map: URIRef MapCategoryType: URIRef MarryAction: URIRef Mass: URIRef MediaGallery: URIRef MediaObject: URIRef MediaSubscription: URIRef MedicalOrganization: URIRef MeetingRoom: URIRef MensClothingStore: URIRef Menu: URIRef MenuItem: URIRef MenuSection: URIRef Message: URIRef MiddleSchool: URIRef MobileApplication: URIRef MobilePhoneStore: URIRef MonetaryAmount: URIRef MonetaryAmountDistribution: URIRef Mosque: URIRef Motel: URIRef MotorcycleDealer: URIRef MotorcycleRepair: URIRef Mountain: URIRef MoveAction: URIRef Movie: URIRef MovieClip: URIRef MovieRentalStore: URIRef MovieSeries: URIRef MovieTheater: URIRef MovingCompany: URIRef Museum: URIRef MusicAlbum: URIRef MusicAlbumProductionType: URIRef MusicAlbumReleaseType: URIRef MusicComposition: URIRef MusicEvent: URIRef MusicGroup: URIRef MusicPlaylist: URIRef MusicRecording: URIRef MusicRelease: URIRef MusicReleaseFormatType: URIRef MusicStore: URIRef MusicVenue: URIRef MusicVideoObject: URIRef NGO: URIRef NailSalon: URIRef NewsArticle: URIRef NightClub: URIRef Notary: URIRef NoteDigitalDocument: URIRef Number: URIRef NutritionInformation: URIRef Occupation: URIRef OceanBodyOfWater: URIRef Offer: URIRef OfferCatalog: URIRef OfferItemCondition: URIRef OfficeEquipmentStore: URIRef OnDemandEvent: URIRef OpeningHoursSpecification: URIRef Order: URIRef OrderAction: URIRef OrderItem: URIRef OrderStatus: URIRef Organization: URIRef OrganizationRole: URIRef OrganizeAction: URIRef OutletStore: URIRef OwnershipInfo: URIRef PaintAction: URIRef Painting: URIRef ParcelDelivery: URIRef ParcelService: URIRef ParentAudience: URIRef Park: URIRef ParkingFacility: URIRef PawnShop: URIRef PayAction: URIRef PaymentCard: URIRef PaymentChargeSpecification: URIRef PaymentMethod: URIRef PaymentService: URIRef PaymentStatusType: URIRef PeopleAudience: URIRef PerformAction: URIRef PerformanceRole: URIRef PerformingArtsTheater: URIRef PerformingGroup: URIRef Periodical: URIRef Permit: URIRef Person: URIRef PetStore: URIRef Pharmacy: URIRef Photograph: URIRef PhotographAction: URIRef Physician: URIRef Place: URIRef PlaceOfWorship: URIRef PlanAction: URIRef PlayAction: URIRef Playground: URIRef Plumber: URIRef PoliceStation: URIRef Pond: URIRef PostOffice: URIRef PostalAddress: URIRef PreOrderAction: URIRef PrependAction: URIRef Preschool: URIRef PresentationDigitalDocument: URIRef PriceSpecification: URIRef Product: URIRef ProductModel: URIRef ProfessionalService: URIRef ProfilePage: URIRef ProgramMembership: URIRef PropertyValue: URIRef PropertyValueSpecification: URIRef PublicSwimmingPool: URIRef PublicationEvent: URIRef PublicationIssue: URIRef PublicationVolume: URIRef QAPage: URIRef QualitativeValue: URIRef QuantitativeValue: URIRef QuantitativeValueDistribution: URIRef Quantity: URIRef Question: URIRef QuoteAction: URIRef RVPark: URIRef RadioChannel: URIRef RadioClip: URIRef RadioEpisode: URIRef RadioSeason: URIRef RadioSeries: URIRef RadioStation: URIRef Rating: URIRef ReactAction: URIRef ReadAction: URIRef RealEstateAgent: URIRef ReceiveAction: URIRef Recipe: URIRef RecyclingCenter: URIRef RegisterAction: URIRef RejectAction: URIRef RentAction: URIRef RentalCarReservation: URIRef ReplaceAction: URIRef ReplyAction: URIRef Report: URIRef Reservation: URIRef ReservationPackage: URIRef ReservationStatusType: URIRef ReserveAction: URIRef Reservoir: URIRef Residence: URIRef Resort: URIRef Restaurant: URIRef RestrictedDiet: URIRef ResumeAction: URIRef ReturnAction: URIRef Review: URIRef ReviewAction: URIRef RiverBodyOfWater: URIRef Role: URIRef RoofingContractor: URIRef Room: URIRef RsvpAction: URIRef RsvpResponseType: URIRef SaleEvent: URIRef ScheduleAction: URIRef ScholarlyArticle: URIRef School: URIRef ScreeningEvent: URIRef Sculpture: URIRef SeaBodyOfWater: URIRef SearchAction: URIRef SearchResultsPage: URIRef Season: URIRef Seat: URIRef SelfStorage: URIRef SellAction: URIRef SendAction: URIRef Series: URIRef Service: URIRef ServiceChannel: URIRef ShareAction: URIRef ShoeStore: URIRef ShoppingCenter: URIRef SingleFamilyResidence: URIRef SiteNavigationElement: URIRef SkiResort: URIRef SocialEvent: URIRef SocialMediaPosting: URIRef SoftwareApplication: URIRef SoftwareSourceCode: URIRef SomeProducts: URIRef SpeakableSpecification: URIRef Specialty: URIRef SportingGoodsStore: URIRef SportsActivityLocation: URIRef SportsClub: URIRef SportsEvent: URIRef SportsOrganization: URIRef SportsTeam: URIRef SpreadsheetDigitalDocument: URIRef StadiumOrArena: URIRef State: URIRef SteeringPositionValue: URIRef Store: URIRef StructuredValue: URIRef SubscribeAction: URIRef SubwayStation: URIRef Suite: URIRef SuspendAction: URIRef Synagogue: URIRef TVClip: URIRef TVEpisode: URIRef TVSeason: URIRef TVSeries: URIRef Table: URIRef TakeAction: URIRef TattooParlor: URIRef Taxi: URIRef TaxiReservation: URIRef TaxiService: URIRef TaxiStand: URIRef TechArticle: URIRef TelevisionChannel: URIRef TelevisionStation: URIRef TennisComplex: URIRef Text: URIRef TextDigitalDocument: URIRef TheaterEvent: URIRef TheaterGroup: URIRef Thing: URIRef Ticket: URIRef TieAction: URIRef Time: URIRef TipAction: URIRef TireShop: URIRef TouristAttraction: URIRef TouristInformationCenter: URIRef ToyStore: URIRef TrackAction: URIRef TradeAction: URIRef TrainReservation: URIRef TrainStation: URIRef TrainTrip: URIRef TransferAction: URIRef TravelAction: URIRef TravelAgency: URIRef Trip: URIRef TypeAndQuantityNode: URIRef URL: URIRef UnRegisterAction: URIRef UnitPriceSpecification: URIRef UpdateAction: URIRef UseAction: URIRef UserBlocks: URIRef UserCheckins: URIRef UserComments: URIRef UserDownloads: URIRef UserInteraction: URIRef UserLikes: URIRef UserPageVisits: URIRef UserPlays: URIRef UserPlusOnes: URIRef UserTweets: URIRef Vehicle: URIRef VideoGallery: URIRef VideoGame: URIRef VideoGameClip: URIRef VideoGameSeries: URIRef VideoObject: URIRef ViewAction: URIRef VisualArtsEvent: URIRef VisualArtwork: URIRef Volcano: URIRef VoteAction: URIRef WPAdBlock: URIRef WPFooter: URIRef WPHeader: URIRef WPSideBar: URIRef WantAction: URIRef WarrantyPromise: URIRef WarrantyScope: URIRef WatchAction: URIRef Waterfall: URIRef WearAction: URIRef WebApplication: URIRef WebPage: URIRef WebPageElement: URIRef WebSite: URIRef WholesaleStore: URIRef WinAction: URIRef Winery: URIRef WorkersUnion: URIRef WriteAction: URIRef Zoo: URIRef cwl_utils-0.41/mypy-stubs/rdflib/namespace/_SH.pyi0000644000000000000000000001154513615410400017117 0ustar00from rdflib.namespace import DefinedNamespace as DefinedNamespace from rdflib.namespace import Namespace as Namespace from rdflib.term import URIRef as URIRef class SH(DefinedNamespace): alternativePath: URIRef annotationProperty: URIRef annotationValue: URIRef annotationVarName: URIRef ask: URIRef closed: URIRef condition: URIRef conforms: URIRef construct: URIRef datatype: URIRef deactivated: URIRef declare: URIRef defaultValue: URIRef description: URIRef detail: URIRef disjoint: URIRef entailment: URIRef equals: URIRef expression: URIRef filterShape: URIRef flags: URIRef focusNode: URIRef group: URIRef hasValue: URIRef ignoredProperties: URIRef intersection: URIRef inversePath: URIRef js: URIRef jsFunctionName: URIRef jsLibrary: URIRef jsLibraryURL: URIRef labelTemplate: URIRef languageIn: URIRef lessThan: URIRef lessThanOrEquals: URIRef maxCount: URIRef maxExclusive: URIRef maxInclusive: URIRef maxLength: URIRef message: URIRef minCount: URIRef minExclusive: URIRef minInclusive: URIRef minLength: URIRef name: URIRef namespace: URIRef node: URIRef nodeKind: URIRef nodeValidator: URIRef nodes: URIRef object: URIRef oneOrMorePath: URIRef optional: URIRef order: URIRef parameter: URIRef path: URIRef pattern: URIRef predicate: URIRef prefix: URIRef prefixes: URIRef property: URIRef propertyValidator: URIRef qualifiedMaxCount: URIRef qualifiedMinCount: URIRef qualifiedValueShape: URIRef qualifiedValueShapesDisjoint: URIRef result: URIRef resultAnnotation: URIRef resultMessage: URIRef resultPath: URIRef resultSeverity: URIRef returnType: URIRef rule: URIRef select: URIRef severity: URIRef shapesGraph: URIRef shapesGraphWellFormed: URIRef sourceConstraint: URIRef sourceConstraintComponent: URIRef sourceShape: URIRef sparql: URIRef subject: URIRef suggestedShapesGraph: URIRef target: URIRef targetClass: URIRef targetNode: URIRef targetObjectsOf: URIRef targetSubjectsOf: URIRef union: URIRef uniqueLang: URIRef update: URIRef validator: URIRef value: URIRef xone: URIRef zeroOrMorePath: URIRef zeroOrOnePath: URIRef AbstractResult: URIRef ConstraintComponent: URIRef Function: URIRef JSConstraint: URIRef JSExecutable: URIRef JSFunction: URIRef JSLibrary: URIRef JSRule: URIRef JSTarget: URIRef JSTargetType: URIRef JSValidator: URIRef NodeKind: URIRef NodeShape: URIRef Parameter: URIRef Parameterizable: URIRef PrefixDeclaration: URIRef PropertyGroup: URIRef PropertyShape: URIRef ResultAnnotation: URIRef Rule: URIRef SPARQLAskExecutable: URIRef SPARQLAskValidator: URIRef SPARQLConstraint: URIRef SPARQLConstructExecutable: URIRef SPARQLExecutable: URIRef SPARQLFunction: URIRef SPARQLRule: URIRef SPARQLSelectExecutable: URIRef SPARQLSelectValidator: URIRef SPARQLTarget: URIRef SPARQLTargetType: URIRef SPARQLUpdateExecutable: URIRef Severity: URIRef Shape: URIRef Target: URIRef TargetType: URIRef TripleRule: URIRef ValidationReport: URIRef ValidationResult: URIRef Validator: URIRef this: URIRef AndConstraintComponent: URIRef ClassConstraintComponent: URIRef ClosedConstraintComponent: URIRef DatatypeConstraintComponent: URIRef DisjointConstraintComponent: URIRef EqualsConstraintComponent: URIRef ExpressionConstraintComponent: URIRef HasValueConstraintComponent: URIRef InConstraintComponent: URIRef JSConstraintComponent: URIRef LanguageInConstraintComponent: URIRef LessThanConstraintComponent: URIRef LessThanOrEqualsConstraintComponent: URIRef MaxCountConstraintComponent: URIRef MaxExclusiveConstraintComponent: URIRef MaxInclusiveConstraintComponent: URIRef MaxLengthConstraintComponent: URIRef MinCountConstraintComponent: URIRef MinExclusiveConstraintComponent: URIRef MinInclusiveConstraintComponent: URIRef MinLengthConstraintComponent: URIRef NodeConstraintComponent: URIRef NodeKindConstraintComponent: URIRef NotConstraintComponent: URIRef OrConstraintComponent: URIRef PatternConstraintComponent: URIRef PropertyConstraintComponent: URIRef QualifiedMaxCountConstraintComponent: URIRef QualifiedMinCountConstraintComponent: URIRef SPARQLConstraintComponent: URIRef UniqueLangConstraintComponent: URIRef XoneConstraintComponent: URIRef BlankNode: URIRef BlankNodeOrIRI: URIRef BlankNodeOrLiteral: URIRef IRI: URIRef IRIOrLiteral: URIRef Literal: URIRef Info: URIRef Violation: URIRef Warning: URIRef cwl_utils-0.41/mypy-stubs/rdflib/namespace/_SKOS.pyi0000644000000000000000000000165713615410400017367 0ustar00from rdflib.namespace import DefinedNamespace as DefinedNamespace from rdflib.namespace import Namespace as Namespace from rdflib.term import URIRef as URIRef class SKOS(DefinedNamespace): altLabel: URIRef broadMatch: URIRef broader: URIRef broaderTransitive: URIRef changeNote: URIRef closeMatch: URIRef definition: URIRef editorialNote: URIRef exactMatch: URIRef example: URIRef hasTopConcept: URIRef hiddenLabel: URIRef historyNote: URIRef inScheme: URIRef mappingRelation: URIRef member: URIRef memberList: URIRef narrowMatch: URIRef narrower: URIRef narrowerTransitive: URIRef notation: URIRef note: URIRef prefLabel: URIRef related: URIRef relatedMatch: URIRef scopeNote: URIRef semanticRelation: URIRef topConceptOf: URIRef Collection: URIRef Concept: URIRef ConceptScheme: URIRef OrderedCollection: URIRef cwl_utils-0.41/mypy-stubs/rdflib/namespace/_SOSA.pyi0000644000000000000000000000206313615410400017345 0ustar00from rdflib.namespace import DefinedNamespace as DefinedNamespace from rdflib.namespace import Namespace as Namespace from rdflib.term import URIRef as URIRef class SOSA(DefinedNamespace): ActuatableProperty: URIRef Actuation: URIRef Actuator: URIRef FeatureOfInterest: URIRef ObservableProperty: URIRef Observation: URIRef Platform: URIRef Procedure: URIRef Result: URIRef Sample: URIRef Sampler: URIRef Sampling: URIRef Sensor: URIRef hasSimpleResult: URIRef resultTime: URIRef actsOnProperty: URIRef hasFeatureOfInterest: URIRef hasResult: URIRef hasSample: URIRef hosts: URIRef isActedOnBy: URIRef isFeatureOfInterestOf: URIRef isHostedBy: URIRef isObservedBy: URIRef isResultOf: URIRef isSampleOf: URIRef madeActuation: URIRef madeByActuator: URIRef madeBySampler: URIRef madeBySensor: URIRef madeObservation: URIRef madeSampling: URIRef observedProperty: URIRef observes: URIRef phenomenonTime: URIRef usedProcedure: URIRef cwl_utils-0.41/mypy-stubs/rdflib/namespace/_SSN.pyi0000644000000000000000000000125013615410400017240 0ustar00from rdflib.namespace import DefinedNamespace as DefinedNamespace from rdflib.namespace import Namespace as Namespace from rdflib.term import URIRef as URIRef class SSN(DefinedNamespace): Deployment: URIRef Input: URIRef Output: URIRef Property: URIRef Stimulus: URIRef System: URIRef wasOriginatedBy: URIRef deployedOnPlatform: URIRef deployedSystem: URIRef detects: URIRef forProperty: URIRef hasDeployment: URIRef hasInput: URIRef hasOutput: URIRef hasProperty: URIRef hasSubSystem: URIRef implementedBy: URIRef implements: URIRef inDeployment: URIRef isPropertyOf: URIRef isProxyFor: URIRef cwl_utils-0.41/mypy-stubs/rdflib/namespace/_TIME.pyi0000644000000000000000000000463613615410400017346 0ustar00from rdflib.namespace import DefinedNamespace as DefinedNamespace from rdflib.namespace import Namespace as Namespace from rdflib.term import URIRef as URIRef class TIME(DefinedNamespace): generalDay: URIRef generalMonth: URIRef generalYear: URIRef DateTimeDescription: URIRef DateTimeInterval: URIRef DayOfWeek: URIRef Duration: URIRef DurationDescription: URIRef GeneralDateTimeDescription: URIRef GeneralDurationDescription: URIRef Instant: URIRef Interval: URIRef MonthOfYear: URIRef ProperInterval: URIRef TRS: URIRef TemporalDuration: URIRef TemporalEntity: URIRef TemporalPosition: URIRef TemporalUnit: URIRef TimePosition: URIRef TimeZone: URIRef day: URIRef dayOfYear: URIRef days: URIRef hasXSDDuration: URIRef hour: URIRef hours: URIRef inXSDDate: URIRef inXSDDateTimeStamp: URIRef inXSDgYear: URIRef inXSDgYearMonth: URIRef minute: URIRef minutes: URIRef month: URIRef months: URIRef nominalPosition: URIRef numericDuration: URIRef numericPosition: URIRef second: URIRef seconds: URIRef week: URIRef weeks: URIRef year: URIRef years: URIRef January: URIRef Year: URIRef inXSDDateTime: URIRef xsdDateTime: URIRef hasTRS: URIRef after: URIRef dayOfWeek: URIRef hasBeginning: URIRef hasDateTimeDescription: URIRef hasDuration: URIRef hasDurationDescription: URIRef hasEnd: URIRef hasTemporalDuration: URIRef hasTime: URIRef inDateTime: URIRef inTemporalPosition: URIRef inTimePosition: URIRef inside: URIRef intervalAfter: URIRef intervalBefore: URIRef intervalContains: URIRef intervalDisjoint: URIRef intervalDuring: URIRef intervalEquals: URIRef intervalFinishedBy: URIRef intervalFinishes: URIRef intervalIn: URIRef intervalMeets: URIRef intervalMetBy: URIRef intervalOverlappedBy: URIRef intervalOverlaps: URIRef intervalStartedBy: URIRef intervalStarts: URIRef monthOfYear: URIRef timeZone: URIRef unitType: URIRef before: URIRef Friday: URIRef Monday: URIRef Saturday: URIRef Sunday: URIRef Thursday: URIRef Tuesday: URIRef Wednesday: URIRef unitDay: URIRef unitHour: URIRef unitMinute: URIRef unitMonth: URIRef unitSecond: URIRef unitWeek: URIRef unitYear: URIRef cwl_utils-0.41/mypy-stubs/rdflib/namespace/_VOID.pyi0000644000000000000000000000163713615410400017347 0ustar00from rdflib.namespace import DefinedNamespace as DefinedNamespace from rdflib.namespace import Namespace as Namespace from rdflib.term import URIRef as URIRef class VOID(DefinedNamespace): classPartition: URIRef classes: URIRef dataDump: URIRef distinctObjects: URIRef distinctSubjects: URIRef documents: URIRef entities: URIRef exampleResource: URIRef feature: URIRef inDataset: URIRef linkPredicate: URIRef objectsTarget: URIRef openSearchDescription: URIRef properties: URIRef property: URIRef propertyPartition: URIRef rootResource: URIRef sparqlEndpoint: URIRef subjectsTarget: URIRef subset: URIRef target: URIRef triples: URIRef uriLookupEndpoint: URIRef uriRegexPattern: URIRef uriSpace: URIRef vocabulary: URIRef Dataset: URIRef DatasetDescription: URIRef Linkset: URIRef TechnicalFeature: URIRef cwl_utils-0.41/mypy-stubs/rdflib/namespace/_XSD.pyi0000644000000000000000000000331613615410400017240 0ustar00from rdflib.namespace import DefinedNamespace as DefinedNamespace from rdflib.namespace import Namespace as Namespace from rdflib.term import URIRef as URIRef class XSD(DefinedNamespace): ENTITIES: URIRef ENTITY: URIRef ID: URIRef IDREF: URIRef IDREFS: URIRef NCName: URIRef NMTOKEN: URIRef NMTOKENS: URIRef NOTATION: URIRef Name: URIRef QName: URIRef anyURI: URIRef base64Binary: URIRef boolean: URIRef byte: URIRef date: URIRef dateTime: URIRef dateTimeStamp: URIRef dayTimeDuration: URIRef decimal: URIRef double: URIRef duration: URIRef float: URIRef gDay: URIRef gMonth: URIRef gMonthDay: URIRef gYear: URIRef gYearMonth: URIRef hexBinary: URIRef int: URIRef integer: URIRef language: URIRef long: URIRef negativeInteger: URIRef nonNegativeInteger: URIRef nonPositiveInteger: URIRef normalizedString: URIRef positiveInteger: URIRef short: URIRef string: URIRef time: URIRef token: URIRef unsignedByte: URIRef unsignedInt: URIRef unsignedLong: URIRef unsignedShort: URIRef yearMonthDuration: URIRef ordered: URIRef bounded: URIRef cardinality: URIRef numeric: URIRef length: URIRef minLength: URIRef maxLength: URIRef pattern: URIRef enumeration: URIRef whiteSpace: URIRef maxExclusive: URIRef maxInclusive: URIRef minExclusive: URIRef minInclusive: URIRef totalDigits: URIRef fractionDigits: URIRef Assertions: URIRef explicitTimezone: URIRef year: URIRef month: URIRef day: URIRef hour: URIRef minute: URIRef second: URIRef timezoneOffset: URIRef cwl_utils-0.41/mypy-stubs/rdflib/namespace/__init__.pyi0000644000000000000000000000435213615410400020203 0ustar00from typing import Any, Tuple from rdflib.term import URIRef __all__ = [ "split_uri", "Namespace", "ClosedNamespace", "RDF", "RDFS", "CSVW", "DC", "DCAT", "DCTERMS", "DOAP", "FOAF", "ODRL2", "ORG", "OWL", "PROF", "PROV", "QB", "SDO", "SH", "SKOS", "SOSA", "SSN", "TIME", "VOID", "XSD", "OWL", ] class Namespace(str): @property def title(self) -> URIRef: ... # type: ignore[override] def term(self, name: Any) -> URIRef: ... def __getitem__(self, key: Any) -> URIRef: ... def __getattr__(self, name: str) -> URIRef: ... class URIPattern(str): def format(self, *args: Any, **kwargs: Any) -> str: ... class DefinedNamespaceMeta(type): def __getitem__(cls, name: Any, default: Any | None = ...) -> URIRef: ... def __getattr__(cls, name: Any) -> URIRef: ... def __contains__(cls, item: Any) -> bool: ... class DefinedNamespace(metaclass=DefinedNamespaceMeta): def __init__(self) -> None: ... class ClosedNamespace(Namespace): def __new__(cls, uri: Any, terms: Any) -> ClosedNamespace: ... @property def uri(self) -> str: ... NAME_START_CATEGORIES = ["Ll", "Lu", "Lo", "Lt", "Nl"] SPLIT_START_CATEGORIES = NAME_START_CATEGORIES + ["Nd"] XMLNS = "http://www.w3.org/XML/1998/namespace" def split_uri(uri: Any, split_start: Any = ...) -> tuple[str, str]: ... from rdflib.namespace._CSVW import CSVW from rdflib.namespace._DC import DC from rdflib.namespace._DCAT import DCAT from rdflib.namespace._DCTERMS import DCTERMS from rdflib.namespace._DOAP import DOAP from rdflib.namespace._FOAF import FOAF from rdflib.namespace._ODRL2 import ODRL2 from rdflib.namespace._ORG import ORG from rdflib.namespace._OWL import OWL from rdflib.namespace._PROF import PROF from rdflib.namespace._PROV import PROV from rdflib.namespace._QB import QB from rdflib.namespace._RDF import RDF from rdflib.namespace._RDFS import RDFS from rdflib.namespace._SDO import SDO from rdflib.namespace._SH import SH from rdflib.namespace._SKOS import SKOS from rdflib.namespace._SOSA import SOSA from rdflib.namespace._SSN import SSN from rdflib.namespace._TIME import TIME from rdflib.namespace._VOID import VOID from rdflib.namespace._XSD import XSD cwl_utils-0.41/mypy-stubs/rdflib/plugins/__init__.pyi0000644000000000000000000000016613615410400017727 0ustar00# Stubs for rdflib.plugins (Python 3.5) # # NOTE: This dynamically typed stub was automatically generated by stubgen. cwl_utils-0.41/mypy-stubs/rdflib/plugins/parsers/__init__.pyi0000644000000000000000000000017613615410400021407 0ustar00# Stubs for rdflib.plugins.parsers (Python 3.5) # # NOTE: This dynamically typed stub was automatically generated by stubgen. cwl_utils-0.41/mypy-stubs/rdflib/plugins/parsers/notation3.pyi0000644000000000000000000000004213615410400021556 0ustar00class BadSyntax(SyntaxError): ... cwl_utils-0.41/mypy-stubs/ruamel/__init__.py0000644000000000000000000000000013615410400016103 0ustar00cwl_utils-0.41/mypy.ini0000644000000000000000000000026013615410400012060 0ustar00[mypy] show_error_context = true show_column_numbers = true show_error_codes = true pretty = true strict = true local_partial_types = true [mypy-ruamel.*] ignore_errors = True cwl_utils-0.41/tox.ini0000644000000000000000000000360513615410400011702 0ustar00[tox] envlist = py3{10,11,12,13,14}-lint, py3{10,11,12,13,14}-unit, py3{10,11,12,13,14}-bandit, py3{10,11,12,13,14}-mypy, py312-lint-readme, py312-pydocstyle isolated_build = True skip_missing_interpreters = True [gh-actions] python = 3.10: py310 3.11: py311 3.12: py312 3.13: py313 3.14: py314 [testenv] description = py3{10,11,12,13,14}-unit: Run the unit tests py3{10,11,12,13,14}-lint: Lint the Python code py3{10,11,12,13,14}-bandit: Search for common security issues py3{10,11,12,13,14}-mypy: Check for type safety py312-pydocstyle: docstring style checker py312-lint-readme: Lint the README.rst->.md conversion passenv = CI GITHUB_* deps = py3{10,11,12,13,14}-lint: -rlint-requirements.txt py3{10,11,12,13,14}-bandit: bandit[toml] py3{10,11,12,13,14}-mypy: -rmypy-requirements.txt setenv = py3{10,11,12,13,14}-unit: LC_ALL = C.UTF-8 commands = py3{10,11,12,13,14}-unit: python -m pip install -U pip setuptools wheel py3{10,11,12,13,14}-unit: make coverage-report coverage.xml PYTEST_EXTRA={posargs} py3{10,11,12,13,14}-bandit: bandit --configfile pyproject.toml --recursive cwl_utils py3{10,11,12,13,14}-lint: make flake8 py3{10,11,12,13,14}-lint: make format-check py3{10,11,12,13,14}-mypy: make mypy allowlist_externals = py3{10,11,12,13,14}-lint: flake8 py3{10,11,12,13,14}-lint: black py3{10,11,12,13,14}-{mypy,shellcheck,lint,unit}: make skip_install = py3{10,11,12,13,14}-lint: true py3{10,11,12,13,14}-bandit: true extras = py3{10,11,12,13,14}-mypy: testing py3{10,11,12,13,14}-unit: pretty, testing [testenv:py312-pydocstyle] allowlist_externals = make commands = make pydocstyle deps = ruff skip_install = true [testenv:py312-lint-readme] description = Lint the README.rst->.md conversion commands = make clean dist twine check dist/cwl[-_]utils* deps = twine build readme_renderer[rst] skip_install = true cwl_utils-0.41/.gitignore0000644000000000000000000000243313615410400012355 0ustar00# Byte-compiled / optimized / DLL files __pycache__/ *.py[cod] *$py.class # C extensions *.so # Distribution / packaging .Python build/ develop-eggs/ dist/ downloads/ eggs/ .eggs/ lib/ lib64/ parts/ sdist/ var/ wheels/ *.egg-info/ .installed.cfg *.egg MANIFEST # PyInstaller # Usually these files are written by a python script from a template # before PyInstaller builds the exe, so as to inject date/other infos into it. *.manifest *.spec # Installer logs pip-log.txt pip-delete-this-directory.txt # Unit test / coverage reports htmlcov/ .tox/ .coverage .coverage.* .cache nosetests.xml coverage.xml *.cover .hypothesis/ .pytest_cache/ # Translations *.mo *.pot # Django stuff: *.log local_settings.py db.sqlite3 # Flask stuff: instance/ .webassets-cache # Scrapy stuff: .scrapy # Sphinx documentation docs/_build/ docs/autoapi/ # PyBuilder target/ # Jupyter Notebook .ipynb_checkpoints # pyenv .python-version # celery beat schedule file celerybeat-schedule # SageMath parsed files *.sage.py # Environments .env .venv env/ venv/ ENV/ env.bak/ venv.bak/ # Spyder project settings .spyderproject .spyproject # Rope project settings .ropeproject # mkdocs documentation /site # mypy .mypy_cache/ .vscode/ testenv*/ # PyCharm .idea/ # Backup files *.orig *~ # Temporary files *.swp cwl_utils-0.41/LICENSE0000644000000000000000000002613613615410400011400 0ustar00 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. cwl_utils-0.41/README.rst0000644000000000000000000001402713615410400012056 0ustar00|Linux Build Status| |Code coverage| |Documentation Status| .. |Linux Build Status| image:: https://github.com/common-workflow-language/cwl-utils/actions/workflows/ci-tests.yml/badge.svg?branch=main :target: https://github.com/common-workflow-language/cwl-utils/actions/workflows/ci-tests.yml .. |Code coverage| image:: https://codecov.io/gh/common-workflow-language/cwl-utils/branch/main/graph/badge.svg :target: https://codecov.io/gh/common-workflow-language/cwl-utils .. |Documentation Status| image:: https://readthedocs.org/projects/cwl-utils/badge/?version=latest :target: https://cwl-utils.readthedocs.io/en/latest/?badge=latest :alt: Documentation Status cwl-utils --------- Python Utilities and Autogenerated Classes for loading and parsing `CWL v1.0 `__, `CWL v1.1 `__, and `CWL v1.2 `__ documents. Requires Python 3.8+ Installation ------------ :: pip3 install cwl-utils To install from source:: git clone https://github.com/common-workflow-language/cwl-utils.git cd cwl-utils pip3 install . Usage ----- Pull the all referenced software container images ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ``cwl-docker-extract`` is useful to cache or pre-pull all software container images referenced in a CWL CommandLineTool or CWL Workflow (including all referenced CommandLineTools and sub-Workflows and so on). The default behaviour is to use the Docker engine to download and save the software container images in Docker format. .. code:: bash cwl-docker-extract path_to_my_workflow.cwl .. code:: bash cwl-docker-extract --dir DIRECTORY path_to_my_workflow.cwl Or you can use the Singularity software container engine to download and save the software container images and convert them to the Singularity format at the same time. .. code:: bash cwl-docker-extract --singularity --dir DIRECTORY path_to_my_workflow.cwl Print all referenced software packages ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ``cwl-cite-extract`` prints all software packages found (recursively) in the specified CWL document. Currently the package name and any listed specs and version field are printed for all ``SoftwareRequirement`` s found. .. code:: bash cwl-cite-extract path_to_my_workflow.cwl Replace CWL Expressions with concrete steps ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ``cwl-expression-refactor`` refactors CWL documents so that any CWL Expression evaluations are separate steps (either CWL ExpressionTools or CWL CommandLineTools.) This allows execution by CWL engines that do not want to support inline expression evaluation outside of concrete steps, or do not want to directly support CWL's optional ``InlineJavascriptRequirement`` at all. .. code:: bash cwl-expression-refactor directory/path/to/save/outputs path_to_my_workflow.cwl [more_workflows.cwl] Split a packed CWL document ~~~~~~~~~~~~~~~~~~~~~~~~~~~ ``cwl-graph-split`` splits a packed CWL document file into multiple files. Packed CWL documents use the $graph construct to contain multiple CWL Process objects (Workflow, CommandLineTool, ExpressionTool, Operation). Typically packed CWL documents contain a CWL Workflow under the name "main" and the workflow steps (including any sub-workflows). .. code:: bash cwl-graph-split --outdir optional/directory/path/to/save/outputs path_to_my_workflow.cwl Normalize a CWL document ~~~~~~~~~~~~~~~~~~~~~~~~ ``cwl-normalizer`` normalizes one or more CWL document so that for each document, a JSON format CWL document is produces with it and all of its dependencies packed together, upgrading to CWL v1.2, as needed. Can optionally refactor CWL Expressions into separate steps in the manner of cwl-expression-refactor. .. code:: bash cwl-normalizer directory/path/to/save/outputs path_to_my_workflow.cwl [more_workflows.cwl] Generate for Workflow Parameters from a CWL document ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ``cwl-inputs-schema-gen`` generates a JSON Schema for workflow input parameters from a CWL document. .. code:: bash cwl-inputs-schema-gen path_to_my_workflow.cwl Using the CWL Parsers ~~~~~~~~~~~~~~~~~~~~~ .. code:: python from pathlib import Path from ruamel import yaml import sys from cwl_utils.parser import load_document_by_uri, save # File Input - This is the only thing you will need to adjust or take in as an input to your function: cwl_file = Path("testdata/md5sum.cwl") # or a plain string works as well # Import CWL Object cwl_obj = load_document_by_uri(cwl_file) # View CWL Object print("List of object attributes:\n{}".format("\n".join(map(str, dir(cwl_obj))))) # Export CWL Object into a built-in typed object saved_obj = save(cwl_obj) print(f"Export of the loaded CWL object: {saved_obj}.") Development ----------- Regenerate parsers ~~~~~~~~~~~~~~~~~~ To regenerate install the ``schema_salad`` package and run: ``cwl_utils/parser/cwl_v1_0.py`` was created via ``schema-salad-tool --codegen python https://github.com/common-workflow-language/common-workflow-language/raw/codegen/v1.0/extensions.yml --codegen-parser-info "org.w3id.cwl.v1_0" > cwl_utils/parser/cwl_v1_0.py`` ``cwl_utils/parser/cwl_v1_1.py`` was created via ``schema-salad-tool --codegen python https://github.com/common-workflow-language/cwl-v1.1/raw/codegen/extensions.yml --codegen-parser-info "org.w3id.cwl.v1_1" > cwl_utils/parser/cwl_v1_1.py`` ``cwl_utils/parser/cwl_v1_2.py`` was created via ``schema-salad-tool --codegen python https://github.com/common-workflow-language/cwl-v1.2/raw/codegen/extensions.yml --codegen-parser-info "org.w3id.cwl.v1_2" > cwl_utils/parser/cwl_v1_2.py`` Release ~~~~~~~ To release CWLUtils, bump the version in ``cwl_utils/__meta__.py``, and tag that commit with the new version. The `gh-action-pypi-publish `__ should release that tag. cwl_utils-0.41/pyproject.toml0000644000000000000000000000703213615410400013301 0ustar00[build-system] requires = ["hatchling>=1.27.0"] build-backend = "hatchling.build" [project] name = "cwl-utils" authors = [{name = "Common Workflow Language project contributors", email = "common-workflow-language@googlegroups.com"}] license = {text = "Apache 2.0"} keywords = ["cwl", "commonwl", "common-workflow-language", "sciworkflows"] readme = "README.rst" classifiers = [ "Development Status :: 4 - Beta", "Environment :: Console", "Intended Audience :: Developers", "License :: OSI Approved :: Apache Software License", "Operating System :: POSIX", "Operating System :: MacOS :: MacOS X", "Programming Language :: Python", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", "Programming Language :: Python :: 3.14", "Topic :: File Formats", "Topic :: Scientific/Engineering", "Topic :: Scientific/Engineering :: Information Analysis", "Topic :: Software Development :: Libraries", "Topic :: System :: Distributed Computing", "Typing :: Typed", ] requires-python = ">=3.10,<3.15" dynamic = ["version"] dependencies = [ "cwl-upgrader >= 1.2.3", "packaging", "rdflib", "requests", "schema-salad >= 8.8.20250205075315,<9", "ruamel.yaml >= 0.17.6, < 0.20", "typing_extensions >= 4.10.0", ] [project.urls] Documentation = "https://cwl-utils.readthedocs.io/" Homepage = "https://www.commonwl.org" Repository = "https://github.com/common-workflow-language/cwl-utils" Issues = "https://github.com/common-workflow-language/cwl-utils/issues" Changelog = "https://github.com/common-workflow-language/cwl-utils/releases" "Related Tools" = "https://www.commonwl.org/tools/" [project.optional-dependencies] pretty = ["cwlformat"] testing = [ "pytest<10", "pytest-cov", "pytest-xdist[psutil]", "cwl-utils[pretty]", "pytest-mock >= 1.10.0", "jsonschema >= 4.21.1", "udocker", "cwltool", ] [project.scripts] cwl-cite-extract = "cwl_utils.cite_extract:main" cwl-docker-extract = "cwl_utils.docker_extract:main" cwl-expression-refactor = "cwl_utils.expression_refactor:main" cwl-graph-split = "cwl_utils.graph_split:main" cwl-normalizer = "cwl_utils.normalizer:main" cwl-inputs-schema-gen = "cwl_utils.inputs_schema_gen:main" [tool.pytest.ini_options] testpaths = ["cwl_utils/tests"] addopts = "-rsx -n auto" [tool.hatch.version] path = "cwl_utils/__meta__.py" [tool.hatch.build.targets.sdist] only-include = [ ".flake8", ".coveragerc", "create_cwl_from_objects.py", "CONTRIBUTING.md", "cwl_utils", "docs", "LICENSE", "lint-requirements.txt", "load_cwl_by_path.py", "Makefile", "mypy.ini", "mypy-requirements.txt", "mypy-stubs", "README.rst", "tox.ini" ] [tool.hatch.build.targets.wheel] only-include = [ "cwl_utils", "LICENSE", "README.rst" ] [tool.hatch.build.targets.wheel.hooks.mypyc] enable-by-default = false dependencies = [ "hatch-mypyc>=0.16.0", "mypy==1.19.0", "types-requests", "types-jsonschema", "types-setuptools>=57.4.0", ] require-runtime-dependencies = true include = [ "/cwl_utils/parser", "/cwl_utils/expression.py" ] [tool.hatch.envs.test] features = ["testing"] [tool.isort] profile = "black" [tool.ruff.lint] select = [ "D", # pydocstyle ] ignore = [ "D100", "D101", "D102", "D103", "D104", "D105", "D107", "D203", "D212", ] [tool.bandit] exclude_dirs = ["cwl_utils/tests"] cwl_utils-0.41/PKG-INFO0000644000000000000000000002052113615410400011460 0ustar00Metadata-Version: 2.4 Name: cwl-utils Version: 0.41 Project-URL: Documentation, https://cwl-utils.readthedocs.io/ Project-URL: Homepage, https://www.commonwl.org Project-URL: Repository, https://github.com/common-workflow-language/cwl-utils Project-URL: Issues, https://github.com/common-workflow-language/cwl-utils/issues Project-URL: Changelog, https://github.com/common-workflow-language/cwl-utils/releases Project-URL: Related Tools, https://www.commonwl.org/tools/ Author-email: Common Workflow Language project contributors License: Apache 2.0 License-File: LICENSE Keywords: common-workflow-language,commonwl,cwl,sciworkflows Classifier: Development Status :: 4 - Beta Classifier: Environment :: Console Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: Apache Software License Classifier: Operating System :: MacOS :: MacOS X Classifier: Operating System :: POSIX Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.10 Classifier: Programming Language :: Python :: 3.11 Classifier: Programming Language :: Python :: 3.12 Classifier: Programming Language :: Python :: 3.13 Classifier: Programming Language :: Python :: 3.14 Classifier: Topic :: File Formats Classifier: Topic :: Scientific/Engineering Classifier: Topic :: Scientific/Engineering :: Information Analysis Classifier: Topic :: Software Development :: Libraries Classifier: Topic :: System :: Distributed Computing Classifier: Typing :: Typed Requires-Python: <3.15,>=3.10 Requires-Dist: cwl-upgrader>=1.2.3 Requires-Dist: packaging Requires-Dist: rdflib Requires-Dist: requests Requires-Dist: ruamel-yaml<0.20,>=0.17.6 Requires-Dist: schema-salad<9,>=8.8.20250205075315 Requires-Dist: typing-extensions>=4.10.0 Provides-Extra: pretty Requires-Dist: cwlformat; extra == 'pretty' Provides-Extra: testing Requires-Dist: cwlformat; extra == 'testing' Requires-Dist: cwltool; extra == 'testing' Requires-Dist: jsonschema>=4.21.1; extra == 'testing' Requires-Dist: pytest-cov; extra == 'testing' Requires-Dist: pytest-mock>=1.10.0; extra == 'testing' Requires-Dist: pytest-xdist[psutil]; extra == 'testing' Requires-Dist: pytest<10; extra == 'testing' Requires-Dist: udocker; extra == 'testing' Description-Content-Type: text/x-rst |Linux Build Status| |Code coverage| |Documentation Status| .. |Linux Build Status| image:: https://github.com/common-workflow-language/cwl-utils/actions/workflows/ci-tests.yml/badge.svg?branch=main :target: https://github.com/common-workflow-language/cwl-utils/actions/workflows/ci-tests.yml .. |Code coverage| image:: https://codecov.io/gh/common-workflow-language/cwl-utils/branch/main/graph/badge.svg :target: https://codecov.io/gh/common-workflow-language/cwl-utils .. |Documentation Status| image:: https://readthedocs.org/projects/cwl-utils/badge/?version=latest :target: https://cwl-utils.readthedocs.io/en/latest/?badge=latest :alt: Documentation Status cwl-utils --------- Python Utilities and Autogenerated Classes for loading and parsing `CWL v1.0 `__, `CWL v1.1 `__, and `CWL v1.2 `__ documents. Requires Python 3.8+ Installation ------------ :: pip3 install cwl-utils To install from source:: git clone https://github.com/common-workflow-language/cwl-utils.git cd cwl-utils pip3 install . Usage ----- Pull the all referenced software container images ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ``cwl-docker-extract`` is useful to cache or pre-pull all software container images referenced in a CWL CommandLineTool or CWL Workflow (including all referenced CommandLineTools and sub-Workflows and so on). The default behaviour is to use the Docker engine to download and save the software container images in Docker format. .. code:: bash cwl-docker-extract path_to_my_workflow.cwl .. code:: bash cwl-docker-extract --dir DIRECTORY path_to_my_workflow.cwl Or you can use the Singularity software container engine to download and save the software container images and convert them to the Singularity format at the same time. .. code:: bash cwl-docker-extract --singularity --dir DIRECTORY path_to_my_workflow.cwl Print all referenced software packages ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ``cwl-cite-extract`` prints all software packages found (recursively) in the specified CWL document. Currently the package name and any listed specs and version field are printed for all ``SoftwareRequirement`` s found. .. code:: bash cwl-cite-extract path_to_my_workflow.cwl Replace CWL Expressions with concrete steps ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ``cwl-expression-refactor`` refactors CWL documents so that any CWL Expression evaluations are separate steps (either CWL ExpressionTools or CWL CommandLineTools.) This allows execution by CWL engines that do not want to support inline expression evaluation outside of concrete steps, or do not want to directly support CWL's optional ``InlineJavascriptRequirement`` at all. .. code:: bash cwl-expression-refactor directory/path/to/save/outputs path_to_my_workflow.cwl [more_workflows.cwl] Split a packed CWL document ~~~~~~~~~~~~~~~~~~~~~~~~~~~ ``cwl-graph-split`` splits a packed CWL document file into multiple files. Packed CWL documents use the $graph construct to contain multiple CWL Process objects (Workflow, CommandLineTool, ExpressionTool, Operation). Typically packed CWL documents contain a CWL Workflow under the name "main" and the workflow steps (including any sub-workflows). .. code:: bash cwl-graph-split --outdir optional/directory/path/to/save/outputs path_to_my_workflow.cwl Normalize a CWL document ~~~~~~~~~~~~~~~~~~~~~~~~ ``cwl-normalizer`` normalizes one or more CWL document so that for each document, a JSON format CWL document is produces with it and all of its dependencies packed together, upgrading to CWL v1.2, as needed. Can optionally refactor CWL Expressions into separate steps in the manner of cwl-expression-refactor. .. code:: bash cwl-normalizer directory/path/to/save/outputs path_to_my_workflow.cwl [more_workflows.cwl] Generate for Workflow Parameters from a CWL document ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ``cwl-inputs-schema-gen`` generates a JSON Schema for workflow input parameters from a CWL document. .. code:: bash cwl-inputs-schema-gen path_to_my_workflow.cwl Using the CWL Parsers ~~~~~~~~~~~~~~~~~~~~~ .. code:: python from pathlib import Path from ruamel import yaml import sys from cwl_utils.parser import load_document_by_uri, save # File Input - This is the only thing you will need to adjust or take in as an input to your function: cwl_file = Path("testdata/md5sum.cwl") # or a plain string works as well # Import CWL Object cwl_obj = load_document_by_uri(cwl_file) # View CWL Object print("List of object attributes:\n{}".format("\n".join(map(str, dir(cwl_obj))))) # Export CWL Object into a built-in typed object saved_obj = save(cwl_obj) print(f"Export of the loaded CWL object: {saved_obj}.") Development ----------- Regenerate parsers ~~~~~~~~~~~~~~~~~~ To regenerate install the ``schema_salad`` package and run: ``cwl_utils/parser/cwl_v1_0.py`` was created via ``schema-salad-tool --codegen python https://github.com/common-workflow-language/common-workflow-language/raw/codegen/v1.0/extensions.yml --codegen-parser-info "org.w3id.cwl.v1_0" > cwl_utils/parser/cwl_v1_0.py`` ``cwl_utils/parser/cwl_v1_1.py`` was created via ``schema-salad-tool --codegen python https://github.com/common-workflow-language/cwl-v1.1/raw/codegen/extensions.yml --codegen-parser-info "org.w3id.cwl.v1_1" > cwl_utils/parser/cwl_v1_1.py`` ``cwl_utils/parser/cwl_v1_2.py`` was created via ``schema-salad-tool --codegen python https://github.com/common-workflow-language/cwl-v1.2/raw/codegen/extensions.yml --codegen-parser-info "org.w3id.cwl.v1_2" > cwl_utils/parser/cwl_v1_2.py`` Release ~~~~~~~ To release CWLUtils, bump the version in ``cwl_utils/__meta__.py``, and tag that commit with the new version. The `gh-action-pypi-publish `__ should release that tag.