Validate a CommandLineTool in-memory

I’m trying to write some tests for code that generates CWL. I have a CWL snippet as a string. How do I now validate it against the CommandLineTool schema with the last work?

Lets say I have the a string that looks like this:

baseCommand:
- htseq-count
class: CommandLineTool
cwlVersion: v1.0
id: htseq-count

Currently I’m loading the YAML string back into a dictionary and trying to validate that:

from cwltool.load_tool import load_tool
from ruamel.yaml import load

def validate_cwl(cwl: str):
    parsed = load(cwl)
    load_tool(parsed)

This gets a lot of the way there, except that schema tries to load a file based on its ID, even though this file doesn’t exist:

  File "/media/michael/Storage2/Programming/CliHelpParser/venv/lib/python3.6/site-packages/cwltool/load_tool.py", line 433, in load_tool
    loadingContext, workflowobj, uri
  File "/media/michael/Storage2/Programming/CliHelpParser/venv/lib/python3.6/site-packages/cwltool/load_tool.py", line 337, in resolve_and_validate_document
    processobj, metadata = document_loader.resolve_ref(uri)
  File "/media/michael/Storage2/Programming/CliHelpParser/venv/lib/python3.6/site-packages/schema_salad/ref_resolver.py", line 746, in resolve_ref
    doc = self.fetch(doc_url, inject_ids=(not mixin))
  File "/media/michael/Storage2/Programming/CliHelpParser/venv/lib/python3.6/site-packages/schema_salad/ref_resolver.py", line 1205, in fetch
    text = self.fetch_text(url)
  File "/media/michael/Storage2/Programming/CliHelpParser/venv/lib/python3.6/site-packages/schema_salad/ref_resolver.py", line 205, in fetch_text
    raise ValidationException(str(err)) from err
schema_salad.exceptions.ValidationException: [Errno 2] No such file or directory: '/media/michael/Storage2/Programming/CliHelpParser/htseq-count'

I guess I could write this snippet out to a file, but I feel like that would convolute my code a tad. Is there a way to validate the entire snippet in-memory?

The simplest code I can get working is this. But I don’t love it, because it relies on writing out the file, and also uses a few cwltool internals:

import tempfile
from ruamel.yaml import load
from pathlib import Path


def validate_cwl(cwl: str):
    parsed = load(cwl)
    with tempfile.TemporaryDirectory() as tmpdir:
        tmpdir = Path(tmpdir)
        tmpfile = (tmpdir / parsed['id'])
        tmpfile.write_text(cwl)
        loading_context, workflowobj, uri = fetch_document(str(tmpfile))
        resolve_and_validate_document(loading_context, workflowobj, uri)