Author: Michael R. Crusoe <michael.crusoe@gmail.com>
Description: Adjust to newer version of cwltool
--- toil.orig/src/toil/cwl/cwltoil.py
+++ toil/src/toil/cwl/cwltoil.py
@@ -40,6 +40,7 @@
 
 from schema_salad import validate
 import schema_salad.ref_resolver
+from schema_salad.schema import Names
 
 import cwltool.errors
 import cwltool.load_tool
@@ -58,7 +59,7 @@
                                 get_listing, MapperEnt, visit_class,
                                 normalizeFilesDirs)
 from cwltool.process import (shortname, fill_in_defaults, compute_checksums,
-                             collectFilesAndDirs, add_sizes)
+                             add_sizes)
 from cwltool.secrets import SecretStore
 from cwltool.software_requirements import (
     DependenciesConfiguration, get_container_from_software_requirements)
@@ -389,8 +390,21 @@
     """Copy input files out of the global file store and update location and
     path."""
 
-    jobfiles = []  # type: List[Dict[Text, Any]]
-    collectFilesAndDirs(cwljob, jobfiles)
+    def _collectDirEntries(obj):
+        # type: (Union[Dict[Text, Any], List[Dict[Text, Any]]]) -> Iterator[Dict[Text, Any]]
+        if isinstance(obj, dict):
+            if obj.get("class") in ("File", "Directory"):
+                yield obj
+            else:
+                for sub_obj in obj.values():
+                    for dir_entry in _collectDirEntries(sub_obj):
+                        yield dir_entry
+        elif isinstance(obj, list):
+            for sub_obj in obj:
+                for dir_entry in _collectDirEntries(sub_obj):
+                    yield dir_entry
+
+    jobfiles = list(_collectDirEntries(cwljob))
     pm = ToilPathMapper(
         jobfiles, "", outdir, separateDirs=False, stage_listing=True)
     for f, p in pm.items():
@@ -455,6 +469,7 @@
         self.addChild(realjob)
         return realjob.rv()
 
+
 def _makeNestedTempDir(top, seed, levels=2):
     """
     Gets a temporary directory in the hierarchy of directories under a given
@@ -497,12 +512,29 @@
         if runtime_context.builder:
             builder = runtime_context.builder
         else:
-            builder = cwltool.builder.Builder(cwljob)
-            builder.requirements = self.cwltool.requirements
-            builder.outdir = None
-            builder.tmpdir = None
-            builder.timeout = runtime_context.eval_timeout
-            builder.resources = {}
+            builder = cwltool.builder.Builder(
+                job=cwljob,
+                files=[],
+                bindings=[],
+                schemaDefs={},
+                names=Names(),
+                requirements=self.cwltool.requirements,
+                hints=[],
+                resources={},
+                mutation_manager=None,
+                formatgraph=None,
+                make_fs_access=runtime_context.make_fs_access,
+                fs_access=runtime_context.make_fs_access(''),
+                job_script_provider=None,
+                timeout=runtime_context.eval_timeout,
+                debug=False,
+                js_console=False,
+                force_docker_pull=False,
+                loadListing=u'',
+                outdir=u'',
+                tmpdir=u'',
+                stagedir=u''
+            )
         req = tool.evalResources(builder, runtime_context)
         # pass the default of None if basecommand is empty
         unitName = self.cwltool.tool.get("baseCommand", None)
@@ -530,7 +562,8 @@
         fill_in_defaults(
             self.step_inputs, cwljob,
             self.runtime_context.make_fs_access(""))
-        for inp_id in cwljob.keys():
+        immobile_cwljob_dict = copy.deepcopy(cwljob)
+        for inp_id in immobile_cwljob_dict.keys():
             found = False
             for field in self.cwltool.inputs_record_schema['fields']:
                 if field['name'] == inp_id:
@@ -576,6 +609,7 @@
 
         return output
 
+
 def makeJob(tool, jobobj, step_inputs, runtime_context):
     """Create the correct Toil Job object for the CWL tool (workflow, job, or job
     wrapper for dynamic resource requirements.)
@@ -1079,7 +1113,8 @@
 
     if options.provisioner and not options.jobStore:
         raise NoSuchJobStoreException(
-            'Please specify a jobstore with the --jobStore option when specifying a provisioner.')
+            'Please specify a jobstore with the --jobStore option when '
+            'specifying a provisioner.')
 
     use_container = not options.no_container
 
@@ -1141,9 +1176,9 @@
             document_loader, avsc_names, processobj, metadata, uri = \
                 cwltool.load_tool.validate_document(
                     document_loader, workflowobj, uri,
+                    loading_context.overrides_list, loading_context.metadata,
                     loading_context.enable_dev, loading_context.strict, False,
                     loading_context.fetcher_constructor, False,
-                    loading_context.overrides_list,
                     do_validate=loading_context.do_validate)
             loading_context.overrides_list.extend(
                 metadata.get("cwltool:overrides", []))
@@ -1215,7 +1250,8 @@
                 return 33
 
             wf1.cwljob = initialized_job_order
-            if wf1 is CWLJob:  # Clean up temporary directories only created with CWLJobs.
+            if wf1 is CWLJob:
+                # Clean up temporary directories only created with CWLJobs.
                 wf1.addFollowOnFn(cleanTempDirs, wf1)
             outobj = toil.start(wf1)
 
--- toil.orig/src/toil/common.py
+++ toil/src/toil/common.py
@@ -1083,7 +1083,7 @@
         So far there is no reason to store any old pids.
         """
         with self._jobStore.writeSharedFileStream('pid.log') as f:
-            f.write(str(os.getpid()))
+            f.write(str(os.getpid()).encode('utf-8'))
 
 
 class ToilRestartException(Exception):
--- toil.orig/src/toil/jobGraph.py
+++ toil/src/toil/jobGraph.py
@@ -100,6 +100,9 @@
         # this job
         self.chainedJobs = chainedJobs
 
+    def __hash__(self):
+        return hash(self.jobStoreID)
+
     def setupJobAfterFailure(self, config):
         """
         Reduce the remainingRetryCount if greater than zero and set the memory
