cwl-utils: Common Workflow Language Utilities
cwl-utils is a Python library providing utilities and autogenerated classes for loading, manipulating, and parsing Common Workflow Language (CWL) v1.0, v1.1, and v1.2 documents. It is the reference implementation of CWL, offering comprehensive validation and various tools for working with CWL files. The library is actively maintained with frequent releases, typically several times a year.
Common errors
-
ImportError: cannot import name 'load_document_by_uri' from 'cwl_utils.parser'
cause The `cwl_utils.parser` module or the specific function `load_document_by_uri` might not exist in an older installed version of `cwl-utils`, or the library is not installed correctly.fixEnsure `cwl-utils` is installed: `pip install cwl-utils`. If already installed, try upgrading: `pip install --upgrade cwl-utils`. Verify correct import path from documentation. -
schema_salad.exceptions.ValidationException: ... is not a valid CWL document.
cause The CWL file being loaded does not conform to the Common Workflow Language specification, or it uses a CWL version not fully supported by the installed `cwl-utils` version.fixValidate your CWL document using `cwltool --validate your_workflow.cwl`. Consult the CWL specification for the version you are using. Ensure your `cwl-utils` is up-to-date for the CWL version. -
yaml.scanner.ScannerError: while scanning for the next token Found character that cannot start any token
cause The CWL document (which is typically YAML) contains malformed syntax, such as incorrect indentation, invalid characters, or missing delimiters.fixCarefully inspect the CWL YAML file for syntax errors, especially around the indicated line and column. Use a YAML linter or editor with YAML validation features. -
AttributeError: 'NoneType' object has no attribute 'id'
cause `load_document_by_uri` or a similar parsing function returned `None`, likely because the specified file path was incorrect, the file was empty, or an internal parsing error occurred without raising a more specific exception.fixCheck if the file path passed to `load_document_by_uri` is correct and accessible. Ensure the CWL file is not empty and contains valid CWL content. Add checks for `None` return values after loading.
Warnings
- breaking Dropped support for Python 3.9. Users on Python 3.9 must upgrade to a newer Python version (>=3.10).
- breaking Dropped support for Python 3.8. Users on Python 3.8 must upgrade to a newer Python version (>=3.9).
- gotcha Support for `ruamel.yaml` 0.18+ was introduced, which might cause compatibility issues if your environment uses an older, incompatible version or if specific behaviors of older `ruamel.yaml` were relied upon.
- gotcha Internal parser generation and dependency on `schema-salad` has seen updates across versions (e.g., requiring map & union enabled version). This could subtly change parsing behavior for complex CWL documents.
Install
-
pip install cwl-utils
Imports
- load_document_by_uri
from cwl_utils.parser import load_document_by_uri
- save
from cwl_utils.parser import save
Quickstart
from pathlib import Path
from cwl_utils.parser import load_document_by_uri
# Create a dummy CWL file for the example
cwl_content = """
cwlVersion: v1.2
class: CommandLineTool
baseCommand: echo
inputs:
message:
type: string
default: "Hello World from cwl-utils!"
inputBinding:
position: 1
outputs:
output:
type: stdout
"""
cwl_file_path = Path("hello_world.cwl")
cwl_file_path.write_text(cwl_content)
try:
# Load the CWL object from the file URI
# Note: For local files, str(Path_object) is often needed for older APIs
cwl_obj = load_document_by_uri(str(cwl_file_path))
print(f"Successfully loaded CWL Tool ID: {cwl_obj.id}")
print(f"CWL Version: {cwl_obj.cwlVersion}")
if hasattr(cwl_obj, 'inputs') and cwl_obj.inputs:
print(f"First input message default: {cwl_obj.inputs[0].default}")
except Exception as e:
print(f"An error occurred: {e}")
finally:
# Clean up the dummy file
if cwl_file_path.exists():
cwl_file_path.unlink()