We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
boolean without prefix should not add anything to the command line
thanks to @milos-ljubinkovic for finding this!

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `cwltool/builder.py`
Content:
```
1 from __future__ import absolute_import
2 import copy
3 import os
4 import logging
5 from typing import Any, Callable, Dict, List, Text, Type, Union
6 
7 import six
8 from six import iteritems, string_types
9 
10 import avro
11 import schema_salad.validate as validate
12 from schema_salad.sourceline import SourceLine
13 
14 from . import expression
15 from .errors import WorkflowException
16 from .mutation import MutationManager
17 from .pathmapper import (PathMapper, get_listing, normalizeFilesDirs,
18                          visit_class)
19 from .stdfsaccess import StdFsAccess
20 from .utils import aslist, get_feature, docker_windows_path_adjust, onWindows
21 
22 _logger = logging.getLogger("cwltool")
23 
24 AvroSchemaFromJSONData = avro.schema.make_avsc_object
25 
26 CONTENT_LIMIT = 64 * 1024
27 
28 
29 def substitute(value, replace):  # type: (Text, Text) -> Text
30     if replace[0] == "^":
31         return substitute(value[0:value.rindex('.')], replace[1:])
32     else:
33         return value + replace
34 
35 
36 class Builder(object):
37     def __init__(self):  # type: () -> None
38         self.names = None  # type: avro.schema.Names
39         self.schemaDefs = None  # type: Dict[Text, Dict[Text, Any]]
40         self.files = None  # type: List[Dict[Text, Text]]
41         self.fs_access = None  # type: StdFsAccess
42         self.job = None  # type: Dict[Text, Union[Dict[Text, Any], List, Text]]
43         self.requirements = None  # type: List[Dict[Text, Any]]
44         self.hints = None  # type: List[Dict[Text, Any]]
45         self.outdir = None  # type: Text
46         self.tmpdir = None  # type: Text
47         self.resources = None  # type: Dict[Text, Union[int, Text]]
48         self.bindings = []  # type: List[Dict[Text, Any]]
49         self.timeout = None  # type: int
50         self.pathmapper = None  # type: PathMapper
51         self.stagedir = None  # type: Text
52         self.make_fs_access = None  # type: Type[StdFsAccess]
53         self.debug = False  # type: bool
54         self.js_console = False  # type: bool
55         self.mutation_manager = None  # type: MutationManager
56         self.force_docker_pull = False  # type: bool
57 
58         # One of "no_listing", "shallow_listing", "deep_listing"
59         # Will be default "no_listing" for CWL v1.1
60         self.loadListing = "deep_listing"  # type: Union[None, str]
61 
62         self.find_default_container = None  # type: Callable[[], Text]
63         self.job_script_provider = None  # type: Any
64 
65     def build_job_script(self, commands):
66         # type: (List[Text]) -> Text
67         build_job_script_method = getattr(self.job_script_provider, "build_job_script", None)  # type: Callable[[Builder, Union[List[str],List[Text]]], Text]
68         if build_job_script_method:
69             return build_job_script_method(self, commands)
70         else:
71             return None
72 
73     def bind_input(self, schema, datum, lead_pos=None, tail_pos=None):
74         # type: (Dict[Text, Any], Any, Union[int, List[int]], List[int]) -> List[Dict[Text, Any]]
75         if tail_pos is None:
76             tail_pos = []
77         if lead_pos is None:
78             lead_pos = []
79         bindings = []  # type: List[Dict[Text,Text]]
80         binding = None  # type: Dict[Text,Any]
81         if "inputBinding" in schema and isinstance(schema["inputBinding"], dict):
82             binding = copy.copy(schema["inputBinding"])
83 
84             if "position" in binding:
85                 binding["position"] = aslist(lead_pos) + aslist(binding["position"]) + aslist(tail_pos)
86             else:
87                 binding["position"] = aslist(lead_pos) + [0] + aslist(tail_pos)
88 
89             binding["datum"] = datum
90 
91         # Handle union types
92         if isinstance(schema["type"], list):
93             for t in schema["type"]:
94                 if isinstance(t, (str, Text)) and self.names.has_name(t, ""):
95                     avsc = self.names.get_name(t, "")
96                 elif isinstance(t, dict) and "name" in t and self.names.has_name(t["name"], ""):
97                     avsc = self.names.get_name(t["name"], "")
98                 else:
99                     avsc = AvroSchemaFromJSONData(t, self.names)
100                 if validate.validate(avsc, datum):
101                     schema = copy.deepcopy(schema)
102                     schema["type"] = t
103                     return self.bind_input(schema, datum, lead_pos=lead_pos, tail_pos=tail_pos)
104             raise validate.ValidationException(u"'%s' is not a valid union %s" % (datum, schema["type"]))
105         elif isinstance(schema["type"], dict):
106             st = copy.deepcopy(schema["type"])
107             if binding and "inputBinding" not in st and st["type"] == "array" and "itemSeparator" not in binding:
108                 st["inputBinding"] = {}
109             for k in ("secondaryFiles", "format", "streamable"):
110                 if k in schema:
111                     st[k] = schema[k]
112             bindings.extend(self.bind_input(st, datum, lead_pos=lead_pos, tail_pos=tail_pos))
113         else:
114             if schema["type"] in self.schemaDefs:
115                 schema = self.schemaDefs[schema["type"]]
116 
117             if schema["type"] == "record":
118                 for f in schema["fields"]:
119                     if f["name"] in datum:
120                         bindings.extend(self.bind_input(f, datum[f["name"]], lead_pos=lead_pos, tail_pos=f["name"]))
121                     else:
122                         datum[f["name"]] = f.get("default")
123 
124             if schema["type"] == "array":
125                 for n, item in enumerate(datum):
126                     b2 = None
127                     if binding:
128                         b2 = copy.deepcopy(binding)
129                         b2["datum"] = item
130                     itemschema = {
131                         u"type": schema["items"],
132                         u"inputBinding": b2
133                     }
134                     for k in ("secondaryFiles", "format", "streamable"):
135                         if k in schema:
136                             itemschema[k] = schema[k]
137                     bindings.extend(
138                         self.bind_input(itemschema, item, lead_pos=n, tail_pos=tail_pos))
139                 binding = None
140 
141             if schema["type"] == "File":
142                 self.files.append(datum)
143                 if binding:
144                     if binding.get("loadContents"):
145                         with self.fs_access.open(datum["location"], "rb") as f:
146                             datum["contents"] = f.read(CONTENT_LIMIT)
147 
148                 if "secondaryFiles" in schema:
149                     if "secondaryFiles" not in datum:
150                         datum["secondaryFiles"] = []
151                     for sf in aslist(schema["secondaryFiles"]):
152                         if isinstance(sf, dict) or "$(" in sf or "${" in sf:
153                             sfpath = self.do_eval(sf, context=datum)
154                         else:
155                             sfpath = substitute(datum["basename"], sf)
156                         for sfname in aslist(sfpath):
157                             found = False
158                             for d in datum["secondaryFiles"]:
159                                 if not d.get("basename"):
160                                     d["basename"] = d["location"][d["location"].rindex("/")+1:]
161                                 if d["basename"] == sfname:
162                                     found = True
163                             if not found:
164                                 if isinstance(sfname, dict):
165                                     datum["secondaryFiles"].append(sfname)
166                                 else:
167                                     datum["secondaryFiles"].append({
168                                         "location": datum["location"][0:datum["location"].rindex("/")+1]+sfname,
169                                         "basename": sfname,
170                                         "class": "File"})
171 
172                     normalizeFilesDirs(datum["secondaryFiles"])
173 
174                 def _capture_files(f):
175                     self.files.append(f)
176                     return f
177 
178                 visit_class(datum.get("secondaryFiles", []), ("File", "Directory"), _capture_files)
179 
180             if schema["type"] == "Directory":
181                 ll = self.loadListing or (binding and binding.get("loadListing"))
182                 if ll and ll != "no_listing":
183                     get_listing(self.fs_access, datum, (ll == "deep_listing"))
184                 self.files.append(datum)
185 
186         # Position to front of the sort key
187         if binding:
188             for bi in bindings:
189                 bi["position"] = binding["position"] + bi["position"]
190             bindings.append(binding)
191 
192         return bindings
193 
194     def tostr(self, value):  # type: (Any) -> Text
195         if isinstance(value, dict) and value.get("class") in ("File", "Directory"):
196             if "path" not in value:
197                 raise WorkflowException(u"%s object missing \"path\": %s" % (value["class"], value))
198 
199             # Path adjust for windows file path when passing to docker, docker accepts unix like path only
200             (docker_req, docker_is_req) = get_feature(self, "DockerRequirement")
201             if onWindows() and docker_req is not None:  # docker_req is none only when there is no dockerRequirement mentioned in hints and Requirement
202                 return docker_windows_path_adjust(value["path"])
203             return value["path"]
204         else:
205             return Text(value)
206 
207     def generate_arg(self, binding):  # type: (Dict[Text,Any]) -> List[Text]
208         value = binding.get("datum")
209         if "valueFrom" in binding:
210             with SourceLine(binding, "valueFrom", WorkflowException, _logger.isEnabledFor(logging.DEBUG)):
211                 value = self.do_eval(binding["valueFrom"], context=value)
212 
213         prefix = binding.get("prefix")
214         sep = binding.get("separate", True)
215 
216         l = []  # type: List[Dict[Text,Text]]
217         if isinstance(value, list):
218             if binding.get("itemSeparator"):
219                 l = [binding["itemSeparator"].join([self.tostr(v) for v in value])]
220             elif binding.get("valueFrom"):
221                 value = [self.tostr(v) for v in value]
222                 return ([prefix] if prefix else []) + value
223             elif prefix:
224                 return [prefix]
225             else:
226                 return []
227         elif isinstance(value, dict) and value.get("class") in ("File", "Directory"):
228             l = [value]
229         elif isinstance(value, dict):
230             return [prefix] if prefix else []
231         elif value is True and prefix:
232             return [prefix]
233         elif value is False or value is None:
234             return []
235         else:
236             l = [value]
237 
238         args = []
239         for j in l:
240             if sep:
241                 args.extend([prefix, self.tostr(j)])
242             else:
243                 args.append(prefix + self.tostr(j))
244 
245         return [a for a in args if a is not None]
246 
247     def do_eval(self, ex, context=None, pull_image=True, recursive=False):
248         # type: (Union[Dict[Text, Text], Text], Any, bool, bool) -> Any
249         if recursive:
250             if isinstance(ex, dict):
251                 return {k: self.do_eval(v, context, pull_image, recursive) for k, v in iteritems(ex)}
252             if isinstance(ex, list):
253                 return [self.do_eval(v, context, pull_image, recursive) for v in ex]
254 
255         return expression.do_eval(ex, self.job, self.requirements,
256                                   self.outdir, self.tmpdir,
257                                   self.resources,
258                                   context=context, pull_image=pull_image,
259                                   timeout=self.timeout,
260                                   debug=self.debug,
261                                   js_console=self.js_console,
262                                   force_docker_pull=self.force_docker_pull)
263
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/cwltool/builder.py b/cwltool/builder.py
--- a/cwltool/builder.py
+++ b/cwltool/builder.py
@@ -230,7 +230,7 @@
             return [prefix] if prefix else []
         elif value is True and prefix:
             return [prefix]
-        elif value is False or value is None:
+        elif value is False or value is None or (value is True and not prefix):
             return []
         else:
             l = [value]
@@ -251,7 +251,8 @@
                 return {k: self.do_eval(v, context, pull_image, recursive) for k, v in iteritems(ex)}
             if isinstance(ex, list):
                 return [self.do_eval(v, context, pull_image, recursive) for v in ex]
-
+        if context is None and type(ex) is str and "self" in ex:
+            return None
         return expression.do_eval(ex, self.job, self.requirements,
                                   self.outdir, self.tmpdir,
                                   self.resources,

{"golden_diff": "diff --git a/cwltool/builder.py b/cwltool/builder.py\n--- a/cwltool/builder.py\n+++ b/cwltool/builder.py\n@@ -230,7 +230,7 @@\n             return [prefix] if prefix else []\n         elif value is True and prefix:\n             return [prefix]\n-        elif value is False or value is None:\n+        elif value is False or value is None or (value is True and not prefix):\n             return []\n         else:\n             l = [value]\n@@ -251,7 +251,8 @@\n                 return {k: self.do_eval(v, context, pull_image, recursive) for k, v in iteritems(ex)}\n             if isinstance(ex, list):\n                 return [self.do_eval(v, context, pull_image, recursive) for v in ex]\n-\n+        if context is None and type(ex) is str and \"self\" in ex:\n+            return None\n         return expression.do_eval(ex, self.job, self.requirements,\n                                   self.outdir, self.tmpdir,\n                                   self.resources,\n", "issue": "boolean without prefix should not add anything to the command line\nthanks to @milos-ljubinkovic for finding this!\n", "before_files": [{"content": "from __future__ import absolute_import\nimport copy\nimport os\nimport logging\nfrom typing import Any, Callable, Dict, List, Text, Type, Union\n\nimport six\nfrom six import iteritems, string_types\n\nimport avro\nimport schema_salad.validate as validate\nfrom schema_salad.sourceline import SourceLine\n\nfrom . import expression\nfrom .errors import WorkflowException\nfrom .mutation import MutationManager\nfrom .pathmapper import (PathMapper, get_listing, normalizeFilesDirs,\n                         visit_class)\nfrom .stdfsaccess import StdFsAccess\nfrom .utils import aslist, get_feature, docker_windows_path_adjust, onWindows\n\n_logger = logging.getLogger(\"cwltool\")\n\nAvroSchemaFromJSONData = avro.schema.make_avsc_object\n\nCONTENT_LIMIT = 64 * 1024\n\n\ndef substitute(value, replace):  # type: (Text, Text) -> Text\n    if replace[0] == \"^\":\n        return substitute(value[0:value.rindex('.')], replace[1:])\n    else:\n        return value + replace\n\n\nclass Builder(object):\n    def __init__(self):  # type: () -> None\n        self.names = None  # type: avro.schema.Names\n        self.schemaDefs = None  # type: Dict[Text, Dict[Text, Any]]\n        self.files = None  # type: List[Dict[Text, Text]]\n        self.fs_access = None  # type: StdFsAccess\n        self.job = None  # type: Dict[Text, Union[Dict[Text, Any], List, Text]]\n        self.requirements = None  # type: List[Dict[Text, Any]]\n        self.hints = None  # type: List[Dict[Text, Any]]\n        self.outdir = None  # type: Text\n        self.tmpdir = None  # type: Text\n        self.resources = None  # type: Dict[Text, Union[int, Text]]\n        self.bindings = []  # type: List[Dict[Text, Any]]\n        self.timeout = None  # type: int\n        self.pathmapper = None  # type: PathMapper\n        self.stagedir = None  # type: Text\n        self.make_fs_access = None  # type: Type[StdFsAccess]\n        self.debug = False  # type: bool\n        self.js_console = False  # type: bool\n        self.mutation_manager = None  # type: MutationManager\n        self.force_docker_pull = False  # type: bool\n\n        # One of \"no_listing\", \"shallow_listing\", \"deep_listing\"\n        # Will be default \"no_listing\" for CWL v1.1\n        self.loadListing = \"deep_listing\"  # type: Union[None, str]\n\n        self.find_default_container = None  # type: Callable[[], Text]\n        self.job_script_provider = None  # type: Any\n\n    def build_job_script(self, commands):\n        # type: (List[Text]) -> Text\n        build_job_script_method = getattr(self.job_script_provider, \"build_job_script\", None)  # type: Callable[[Builder, Union[List[str],List[Text]]], Text]\n        if build_job_script_method:\n            return build_job_script_method(self, commands)\n        else:\n            return None\n\n    def bind_input(self, schema, datum, lead_pos=None, tail_pos=None):\n        # type: (Dict[Text, Any], Any, Union[int, List[int]], List[int]) -> List[Dict[Text, Any]]\n        if tail_pos is None:\n            tail_pos = []\n        if lead_pos is None:\n            lead_pos = []\n        bindings = []  # type: List[Dict[Text,Text]]\n        binding = None  # type: Dict[Text,Any]\n        if \"inputBinding\" in schema and isinstance(schema[\"inputBinding\"], dict):\n            binding = copy.copy(schema[\"inputBinding\"])\n\n            if \"position\" in binding:\n                binding[\"position\"] = aslist(lead_pos) + aslist(binding[\"position\"]) + aslist(tail_pos)\n            else:\n                binding[\"position\"] = aslist(lead_pos) + [0] + aslist(tail_pos)\n\n            binding[\"datum\"] = datum\n\n        # Handle union types\n        if isinstance(schema[\"type\"], list):\n            for t in schema[\"type\"]:\n                if isinstance(t, (str, Text)) and self.names.has_name(t, \"\"):\n                    avsc = self.names.get_name(t, \"\")\n                elif isinstance(t, dict) and \"name\" in t and self.names.has_name(t[\"name\"], \"\"):\n                    avsc = self.names.get_name(t[\"name\"], \"\")\n                else:\n                    avsc = AvroSchemaFromJSONData(t, self.names)\n                if validate.validate(avsc, datum):\n                    schema = copy.deepcopy(schema)\n                    schema[\"type\"] = t\n                    return self.bind_input(schema, datum, lead_pos=lead_pos, tail_pos=tail_pos)\n            raise validate.ValidationException(u\"'%s' is not a valid union %s\" % (datum, schema[\"type\"]))\n        elif isinstance(schema[\"type\"], dict):\n            st = copy.deepcopy(schema[\"type\"])\n            if binding and \"inputBinding\" not in st and st[\"type\"] == \"array\" and \"itemSeparator\" not in binding:\n                st[\"inputBinding\"] = {}\n            for k in (\"secondaryFiles\", \"format\", \"streamable\"):\n                if k in schema:\n                    st[k] = schema[k]\n            bindings.extend(self.bind_input(st, datum, lead_pos=lead_pos, tail_pos=tail_pos))\n        else:\n            if schema[\"type\"] in self.schemaDefs:\n                schema = self.schemaDefs[schema[\"type\"]]\n\n            if schema[\"type\"] == \"record\":\n                for f in schema[\"fields\"]:\n                    if f[\"name\"] in datum:\n                        bindings.extend(self.bind_input(f, datum[f[\"name\"]], lead_pos=lead_pos, tail_pos=f[\"name\"]))\n                    else:\n                        datum[f[\"name\"]] = f.get(\"default\")\n\n            if schema[\"type\"] == \"array\":\n                for n, item in enumerate(datum):\n                    b2 = None\n                    if binding:\n                        b2 = copy.deepcopy(binding)\n                        b2[\"datum\"] = item\n                    itemschema = {\n                        u\"type\": schema[\"items\"],\n                        u\"inputBinding\": b2\n                    }\n                    for k in (\"secondaryFiles\", \"format\", \"streamable\"):\n                        if k in schema:\n                            itemschema[k] = schema[k]\n                    bindings.extend(\n                        self.bind_input(itemschema, item, lead_pos=n, tail_pos=tail_pos))\n                binding = None\n\n            if schema[\"type\"] == \"File\":\n                self.files.append(datum)\n                if binding:\n                    if binding.get(\"loadContents\"):\n                        with self.fs_access.open(datum[\"location\"], \"rb\") as f:\n                            datum[\"contents\"] = f.read(CONTENT_LIMIT)\n\n                if \"secondaryFiles\" in schema:\n                    if \"secondaryFiles\" not in datum:\n                        datum[\"secondaryFiles\"] = []\n                    for sf in aslist(schema[\"secondaryFiles\"]):\n                        if isinstance(sf, dict) or \"$(\" in sf or \"${\" in sf:\n                            sfpath = self.do_eval(sf, context=datum)\n                        else:\n                            sfpath = substitute(datum[\"basename\"], sf)\n                        for sfname in aslist(sfpath):\n                            found = False\n                            for d in datum[\"secondaryFiles\"]:\n                                if not d.get(\"basename\"):\n                                    d[\"basename\"] = d[\"location\"][d[\"location\"].rindex(\"/\")+1:]\n                                if d[\"basename\"] == sfname:\n                                    found = True\n                            if not found:\n                                if isinstance(sfname, dict):\n                                    datum[\"secondaryFiles\"].append(sfname)\n                                else:\n                                    datum[\"secondaryFiles\"].append({\n                                        \"location\": datum[\"location\"][0:datum[\"location\"].rindex(\"/\")+1]+sfname,\n                                        \"basename\": sfname,\n                                        \"class\": \"File\"})\n\n                    normalizeFilesDirs(datum[\"secondaryFiles\"])\n\n                def _capture_files(f):\n                    self.files.append(f)\n                    return f\n\n                visit_class(datum.get(\"secondaryFiles\", []), (\"File\", \"Directory\"), _capture_files)\n\n            if schema[\"type\"] == \"Directory\":\n                ll = self.loadListing or (binding and binding.get(\"loadListing\"))\n                if ll and ll != \"no_listing\":\n                    get_listing(self.fs_access, datum, (ll == \"deep_listing\"))\n                self.files.append(datum)\n\n        # Position to front of the sort key\n        if binding:\n            for bi in bindings:\n                bi[\"position\"] = binding[\"position\"] + bi[\"position\"]\n            bindings.append(binding)\n\n        return bindings\n\n    def tostr(self, value):  # type: (Any) -> Text\n        if isinstance(value, dict) and value.get(\"class\") in (\"File\", \"Directory\"):\n            if \"path\" not in value:\n                raise WorkflowException(u\"%s object missing \\\"path\\\": %s\" % (value[\"class\"], value))\n\n            # Path adjust for windows file path when passing to docker, docker accepts unix like path only\n            (docker_req, docker_is_req) = get_feature(self, \"DockerRequirement\")\n            if onWindows() and docker_req is not None:  # docker_req is none only when there is no dockerRequirement mentioned in hints and Requirement\n                return docker_windows_path_adjust(value[\"path\"])\n            return value[\"path\"]\n        else:\n            return Text(value)\n\n    def generate_arg(self, binding):  # type: (Dict[Text,Any]) -> List[Text]\n        value = binding.get(\"datum\")\n        if \"valueFrom\" in binding:\n            with SourceLine(binding, \"valueFrom\", WorkflowException, _logger.isEnabledFor(logging.DEBUG)):\n                value = self.do_eval(binding[\"valueFrom\"], context=value)\n\n        prefix = binding.get(\"prefix\")\n        sep = binding.get(\"separate\", True)\n\n        l = []  # type: List[Dict[Text,Text]]\n        if isinstance(value, list):\n            if binding.get(\"itemSeparator\"):\n                l = [binding[\"itemSeparator\"].join([self.tostr(v) for v in value])]\n            elif binding.get(\"valueFrom\"):\n                value = [self.tostr(v) for v in value]\n                return ([prefix] if prefix else []) + value\n            elif prefix:\n                return [prefix]\n            else:\n                return []\n        elif isinstance(value, dict) and value.get(\"class\") in (\"File\", \"Directory\"):\n            l = [value]\n        elif isinstance(value, dict):\n            return [prefix] if prefix else []\n        elif value is True and prefix:\n            return [prefix]\n        elif value is False or value is None:\n            return []\n        else:\n            l = [value]\n\n        args = []\n        for j in l:\n            if sep:\n                args.extend([prefix, self.tostr(j)])\n            else:\n                args.append(prefix + self.tostr(j))\n\n        return [a for a in args if a is not None]\n\n    def do_eval(self, ex, context=None, pull_image=True, recursive=False):\n        # type: (Union[Dict[Text, Text], Text], Any, bool, bool) -> Any\n        if recursive:\n            if isinstance(ex, dict):\n                return {k: self.do_eval(v, context, pull_image, recursive) for k, v in iteritems(ex)}\n            if isinstance(ex, list):\n                return [self.do_eval(v, context, pull_image, recursive) for v in ex]\n\n        return expression.do_eval(ex, self.job, self.requirements,\n                                  self.outdir, self.tmpdir,\n                                  self.resources,\n                                  context=context, pull_image=pull_image,\n                                  timeout=self.timeout,\n                                  debug=self.debug,\n                                  js_console=self.js_console,\n                                  force_docker_pull=self.force_docker_pull)\n", "path": "cwltool/builder.py"}], "after_files": [{"content": "from __future__ import absolute_import\nimport copy\nimport os\nimport logging\nfrom typing import Any, Callable, Dict, List, Text, Type, Union\n\nimport six\nfrom six import iteritems, string_types\n\nimport avro\nimport schema_salad.validate as validate\nfrom schema_salad.sourceline import SourceLine\n\nfrom . import expression\nfrom .errors import WorkflowException\nfrom .mutation import MutationManager\nfrom .pathmapper import (PathMapper, get_listing, normalizeFilesDirs,\n                         visit_class)\nfrom .stdfsaccess import StdFsAccess\nfrom .utils import aslist, get_feature, docker_windows_path_adjust, onWindows\n\n_logger = logging.getLogger(\"cwltool\")\n\nAvroSchemaFromJSONData = avro.schema.make_avsc_object\n\nCONTENT_LIMIT = 64 * 1024\n\n\ndef substitute(value, replace):  # type: (Text, Text) -> Text\n    if replace[0] == \"^\":\n        return substitute(value[0:value.rindex('.')], replace[1:])\n    else:\n        return value + replace\n\n\nclass Builder(object):\n    def __init__(self):  # type: () -> None\n        self.names = None  # type: avro.schema.Names\n        self.schemaDefs = None  # type: Dict[Text, Dict[Text, Any]]\n        self.files = None  # type: List[Dict[Text, Text]]\n        self.fs_access = None  # type: StdFsAccess\n        self.job = None  # type: Dict[Text, Union[Dict[Text, Any], List, Text]]\n        self.requirements = None  # type: List[Dict[Text, Any]]\n        self.hints = None  # type: List[Dict[Text, Any]]\n        self.outdir = None  # type: Text\n        self.tmpdir = None  # type: Text\n        self.resources = None  # type: Dict[Text, Union[int, Text]]\n        self.bindings = []  # type: List[Dict[Text, Any]]\n        self.timeout = None  # type: int\n        self.pathmapper = None  # type: PathMapper\n        self.stagedir = None  # type: Text\n        self.make_fs_access = None  # type: Type[StdFsAccess]\n        self.debug = False  # type: bool\n        self.js_console = False  # type: bool\n        self.mutation_manager = None  # type: MutationManager\n        self.force_docker_pull = False  # type: bool\n\n        # One of \"no_listing\", \"shallow_listing\", \"deep_listing\"\n        # Will be default \"no_listing\" for CWL v1.1\n        self.loadListing = \"deep_listing\"  # type: Union[None, str]\n\n        self.find_default_container = None  # type: Callable[[], Text]\n        self.job_script_provider = None  # type: Any\n\n    def build_job_script(self, commands):\n        # type: (List[Text]) -> Text\n        build_job_script_method = getattr(self.job_script_provider, \"build_job_script\", None)  # type: Callable[[Builder, Union[List[str],List[Text]]], Text]\n        if build_job_script_method:\n            return build_job_script_method(self, commands)\n        else:\n            return None\n\n    def bind_input(self, schema, datum, lead_pos=None, tail_pos=None):\n        # type: (Dict[Text, Any], Any, Union[int, List[int]], List[int]) -> List[Dict[Text, Any]]\n        if tail_pos is None:\n            tail_pos = []\n        if lead_pos is None:\n            lead_pos = []\n        bindings = []  # type: List[Dict[Text,Text]]\n        binding = None  # type: Dict[Text,Any]\n        if \"inputBinding\" in schema and isinstance(schema[\"inputBinding\"], dict):\n            binding = copy.copy(schema[\"inputBinding\"])\n\n            if \"position\" in binding:\n                binding[\"position\"] = aslist(lead_pos) + aslist(binding[\"position\"]) + aslist(tail_pos)\n            else:\n                binding[\"position\"] = aslist(lead_pos) + [0] + aslist(tail_pos)\n\n            binding[\"datum\"] = datum\n\n        # Handle union types\n        if isinstance(schema[\"type\"], list):\n            for t in schema[\"type\"]:\n                if isinstance(t, (str, Text)) and self.names.has_name(t, \"\"):\n                    avsc = self.names.get_name(t, \"\")\n                elif isinstance(t, dict) and \"name\" in t and self.names.has_name(t[\"name\"], \"\"):\n                    avsc = self.names.get_name(t[\"name\"], \"\")\n                else:\n                    avsc = AvroSchemaFromJSONData(t, self.names)\n                if validate.validate(avsc, datum):\n                    schema = copy.deepcopy(schema)\n                    schema[\"type\"] = t\n                    return self.bind_input(schema, datum, lead_pos=lead_pos, tail_pos=tail_pos)\n            raise validate.ValidationException(u\"'%s' is not a valid union %s\" % (datum, schema[\"type\"]))\n        elif isinstance(schema[\"type\"], dict):\n            st = copy.deepcopy(schema[\"type\"])\n            if binding and \"inputBinding\" not in st and st[\"type\"] == \"array\" and \"itemSeparator\" not in binding:\n                st[\"inputBinding\"] = {}\n            for k in (\"secondaryFiles\", \"format\", \"streamable\"):\n                if k in schema:\n                    st[k] = schema[k]\n            bindings.extend(self.bind_input(st, datum, lead_pos=lead_pos, tail_pos=tail_pos))\n        else:\n            if schema[\"type\"] in self.schemaDefs:\n                schema = self.schemaDefs[schema[\"type\"]]\n\n            if schema[\"type\"] == \"record\":\n                for f in schema[\"fields\"]:\n                    if f[\"name\"] in datum:\n                        bindings.extend(self.bind_input(f, datum[f[\"name\"]], lead_pos=lead_pos, tail_pos=f[\"name\"]))\n                    else:\n                        datum[f[\"name\"]] = f.get(\"default\")\n\n            if schema[\"type\"] == \"array\":\n                for n, item in enumerate(datum):\n                    b2 = None\n                    if binding:\n                        b2 = copy.deepcopy(binding)\n                        b2[\"datum\"] = item\n                    itemschema = {\n                        u\"type\": schema[\"items\"],\n                        u\"inputBinding\": b2\n                    }\n                    for k in (\"secondaryFiles\", \"format\", \"streamable\"):\n                        if k in schema:\n                            itemschema[k] = schema[k]\n                    bindings.extend(\n                        self.bind_input(itemschema, item, lead_pos=n, tail_pos=tail_pos))\n                binding = None\n\n            if schema[\"type\"] == \"File\":\n                self.files.append(datum)\n                if binding:\n                    if binding.get(\"loadContents\"):\n                        with self.fs_access.open(datum[\"location\"], \"rb\") as f:\n                            datum[\"contents\"] = f.read(CONTENT_LIMIT)\n\n                if \"secondaryFiles\" in schema:\n                    if \"secondaryFiles\" not in datum:\n                        datum[\"secondaryFiles\"] = []\n                    for sf in aslist(schema[\"secondaryFiles\"]):\n                        if isinstance(sf, dict) or \"$(\" in sf or \"${\" in sf:\n                            sfpath = self.do_eval(sf, context=datum)\n                        else:\n                            sfpath = substitute(datum[\"basename\"], sf)\n                        for sfname in aslist(sfpath):\n                            found = False\n                            for d in datum[\"secondaryFiles\"]:\n                                if not d.get(\"basename\"):\n                                    d[\"basename\"] = d[\"location\"][d[\"location\"].rindex(\"/\")+1:]\n                                if d[\"basename\"] == sfname:\n                                    found = True\n                            if not found:\n                                if isinstance(sfname, dict):\n                                    datum[\"secondaryFiles\"].append(sfname)\n                                else:\n                                    datum[\"secondaryFiles\"].append({\n                                        \"location\": datum[\"location\"][0:datum[\"location\"].rindex(\"/\")+1]+sfname,\n                                        \"basename\": sfname,\n                                        \"class\": \"File\"})\n\n                    normalizeFilesDirs(datum[\"secondaryFiles\"])\n\n                def _capture_files(f):\n                    self.files.append(f)\n                    return f\n\n                visit_class(datum.get(\"secondaryFiles\", []), (\"File\", \"Directory\"), _capture_files)\n\n            if schema[\"type\"] == \"Directory\":\n                ll = self.loadListing or (binding and binding.get(\"loadListing\"))\n                if ll and ll != \"no_listing\":\n                    get_listing(self.fs_access, datum, (ll == \"deep_listing\"))\n                self.files.append(datum)\n\n        # Position to front of the sort key\n        if binding:\n            for bi in bindings:\n                bi[\"position\"] = binding[\"position\"] + bi[\"position\"]\n            bindings.append(binding)\n\n        return bindings\n\n    def tostr(self, value):  # type: (Any) -> Text\n        if isinstance(value, dict) and value.get(\"class\") in (\"File\", \"Directory\"):\n            if \"path\" not in value:\n                raise WorkflowException(u\"%s object missing \\\"path\\\": %s\" % (value[\"class\"], value))\n\n            # Path adjust for windows file path when passing to docker, docker accepts unix like path only\n            (docker_req, docker_is_req) = get_feature(self, \"DockerRequirement\")\n            if onWindows() and docker_req is not None:  # docker_req is none only when there is no dockerRequirement mentioned in hints and Requirement\n                return docker_windows_path_adjust(value[\"path\"])\n            return value[\"path\"]\n        else:\n            return Text(value)\n\n    def generate_arg(self, binding):  # type: (Dict[Text,Any]) -> List[Text]\n        value = binding.get(\"datum\")\n        if \"valueFrom\" in binding:\n            with SourceLine(binding, \"valueFrom\", WorkflowException, _logger.isEnabledFor(logging.DEBUG)):\n                value = self.do_eval(binding[\"valueFrom\"], context=value)\n\n        prefix = binding.get(\"prefix\")\n        sep = binding.get(\"separate\", True)\n\n        l = []  # type: List[Dict[Text,Text]]\n        if isinstance(value, list):\n            if binding.get(\"itemSeparator\"):\n                l = [binding[\"itemSeparator\"].join([self.tostr(v) for v in value])]\n            elif binding.get(\"valueFrom\"):\n                value = [self.tostr(v) for v in value]\n                return ([prefix] if prefix else []) + value\n            elif prefix:\n                return [prefix]\n            else:\n                return []\n        elif isinstance(value, dict) and value.get(\"class\") in (\"File\", \"Directory\"):\n            l = [value]\n        elif isinstance(value, dict):\n            return [prefix] if prefix else []\n        elif value is True and prefix:\n            return [prefix]\n        elif value is False or value is None or (value is True and not prefix):\n            return []\n        else:\n            l = [value]\n\n        args = []\n        for j in l:\n            if sep:\n                args.extend([prefix, self.tostr(j)])\n            else:\n                args.append(prefix + self.tostr(j))\n\n        return [a for a in args if a is not None]\n\n    def do_eval(self, ex, context=None, pull_image=True, recursive=False):\n        # type: (Union[Dict[Text, Text], Text], Any, bool, bool) -> Any\n        if recursive:\n            if isinstance(ex, dict):\n                return {k: self.do_eval(v, context, pull_image, recursive) for k, v in iteritems(ex)}\n            if isinstance(ex, list):\n                return [self.do_eval(v, context, pull_image, recursive) for v in ex]\n        if context is None and type(ex) is str and \"self\" in ex:\n            return None\n        return expression.do_eval(ex, self.job, self.requirements,\n                                  self.outdir, self.tmpdir,\n                                  self.resources,\n                                  context=context, pull_image=pull_image,\n                                  timeout=self.timeout,\n                                  debug=self.debug,\n                                  js_console=self.js_console,\n                                  force_docker_pull=self.force_docker_pull)\n", "path": "cwltool/builder.py"}]}