We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
UnboundLocalError: local variable 'module_name' referenced before assignment
### Summary
Discovered for myself `nipypecli` and decided to give it a try while composing cmdline invocation just following the errors it was spitting out at me and stopping when error didn't give a hint what I could have specified incorrectly:

```
$> nipypecli convert boutiques -m nipype.interfaces.ants.registration -i ANTS -o test
Traceback (most recent call last):
  File "/usr/bin/nipypecli", line 11, in <module>
    load_entry_point('nipype==1.0.1', 'console_scripts', 'nipypecli')()
  File "/usr/lib/python2.7/dist-packages/click/core.py", line 722, in __call__
    return self.main(*args, **kwargs)
  File "/usr/lib/python2.7/dist-packages/click/core.py", line 697, in main
    rv = self.invoke(ctx)
  File "/usr/lib/python2.7/dist-packages/click/core.py", line 1066, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/usr/lib/python2.7/dist-packages/click/core.py", line 1066, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/usr/lib/python2.7/dist-packages/click/core.py", line 895, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/usr/lib/python2.7/dist-packages/click/core.py", line 535, in invoke
    return callback(*args, **kwargs)
  File "/usr/lib/python2.7/dist-packages/nipype/scripts/cli.py", line 254, in boutiques
    verbose, ignore_template_numbers)
  File "/usr/lib/python2.7/dist-packages/nipype/utils/nipype2boutiques.py", line 56, in generate_boutiques_descriptor
    'command-line'] = "nipype_cmd " + module_name + " " + interface_name + " "
UnboundLocalError: local variable 'module_name' referenced before assignment
```


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `nipype/utils/nipype2boutiques.py`
Content:
```
1 # -*- coding: utf-8 -*-
2 from __future__ import (print_function, division, unicode_literals,
3                         absolute_import)
4 
5 from builtins import str, open
6 # This tool exports a Nipype interface in the Boutiques (https://github.com/boutiques) JSON format.
7 # Boutiques tools can be imported in CBRAIN (https://github.com/aces/cbrain) among other platforms.
8 #
9 # Limitations:
10 #   * List outputs are not supported.
11 #   * Default values are not extracted from the documentation of the Nipype interface.
12 #   * The following input types must be ignored for the output path template creation (see option -t):
13 #     ** String restrictions, i.e. String inputs that accept only a restricted set of values.
14 #     ** mutually exclusive inputs.
15 #   * Path-templates are wrong when output files are not created in the execution directory (e.g. when a sub-directory is created).
16 #   * Optional outputs, i.e. outputs that not always produced, may not be detected.
17 
18 import os
19 import argparse
20 import sys
21 import tempfile
22 import simplejson as json
23 
24 from ..scripts.instance import import_module
25 
26 
27 def generate_boutiques_descriptor(
28         module, interface_name, ignored_template_inputs, docker_image,
29         docker_index, verbose, ignore_template_numbers):
30     '''
31     Returns a JSON string containing a JSON Boutiques description of a Nipype interface.
32     Arguments:
33     * module: module where the Nipype interface is declared.
34     * interface: Nipype interface.
35     * ignored_template_inputs: a list of input names that should be ignored in the generation of output path templates.
36     * ignore_template_numbers: True if numbers must be ignored in output path creations.
37     '''
38 
39     if not module:
40         raise Exception("Undefined module.")
41 
42     # Retrieves Nipype interface
43     if isinstance(module, str):
44         import_module(module)
45         module_name = str(module)
46         module = sys.modules[module]
47 
48     interface = getattr(module, interface_name)()
49     inputs = interface.input_spec()
50     outputs = interface.output_spec()
51 
52     # Tool description
53     tool_desc = {}
54     tool_desc['name'] = interface_name
55     tool_desc[
56         'command-line'] = "nipype_cmd " + module_name + " " + interface_name + " "
57     tool_desc[
58         'description'] = interface_name + ", as implemented in Nipype (module: " + module_name + ", interface: " + interface_name + ")."
59     tool_desc['inputs'] = []
60     tool_desc['outputs'] = []
61     tool_desc['tool-version'] = interface.version
62     tool_desc['schema-version'] = '0.2-snapshot'
63     if docker_image:
64         tool_desc['docker-image'] = docker_image
65     if docker_index:
66         tool_desc['docker-index'] = docker_index
67 
68     # Generates tool inputs
69     for name, spec in sorted(interface.inputs.traits(transient=None).items()):
70         input = get_boutiques_input(inputs, interface, name, spec,
71                                     ignored_template_inputs, verbose,
72                                     ignore_template_numbers)
73         tool_desc['inputs'].append(input)
74         tool_desc['command-line'] += input['command-line-key'] + " "
75         if verbose:
76             print("-> Adding input " + input['name'])
77 
78     # Generates tool outputs
79     for name, spec in sorted(outputs.traits(transient=None).items()):
80         output = get_boutiques_output(name, interface, tool_desc['inputs'],
81                                       verbose)
82         if output['path-template'] != "":
83             tool_desc['outputs'].append(output)
84             if verbose:
85                 print("-> Adding output " + output['name'])
86         elif verbose:
87             print("xx Skipping output " + output['name'] +
88                   " with no path template.")
89     if tool_desc['outputs'] == []:
90         raise Exception("Tool has no output.")
91 
92     # Removes all temporary values from inputs (otherwise they will
93     # appear in the JSON output)
94     for input in tool_desc['inputs']:
95         del input['tempvalue']
96 
97     return json.dumps(tool_desc, indent=4, separators=(',', ': '))
98 
99 
100 def get_boutiques_input(inputs, interface, input_name, spec,
101                         ignored_template_inputs, verbose,
102                         ignore_template_numbers):
103     """
104     Returns a dictionary containing the Boutiques input corresponding to a Nipype intput.
105 
106     Args:
107       * inputs: inputs of the Nipype interface.
108       * interface: Nipype interface.
109       * input_name: name of the Nipype input.
110       * spec: Nipype input spec.
111       * ignored_template_inputs: input names for which no temporary value must be generated.
112       * ignore_template_numbers: True if numbers must be ignored in output path creations.
113 
114     Assumes that:
115       * Input names are unique.
116     """
117     if not spec.desc:
118         spec.desc = "No description provided."
119     spec_info = spec.full_info(inputs, input_name, None)
120 
121     input = {}
122     input['id'] = input_name
123     input['name'] = input_name.replace('_', ' ').capitalize()
124     input['type'] = get_type_from_spec_info(spec_info)
125     input['list'] = is_list(spec_info)
126     input['command-line-key'] = "[" + input_name.upper(
127     ) + "]"  # assumes that input names are unique
128     input['command-line-flag'] = ("--%s" % input_name + " ").strip()
129     input['tempvalue'] = None
130     input['description'] = spec_info.capitalize(
131     ) + ". " + spec.desc.capitalize()
132     if not input['description'].endswith('.'):
133         input['description'] += '.'
134     if not (hasattr(spec, "mandatory") and spec.mandatory):
135         input['optional'] = True
136     else:
137         input['optional'] = False
138     if spec.usedefault:
139         input['default-value'] = spec.default_value()[1]
140 
141     # Create unique, temporary value.
142     temp_value = must_generate_value(input_name, input['type'],
143                                      ignored_template_inputs, spec_info, spec,
144                                      ignore_template_numbers)
145     if temp_value:
146         tempvalue = get_unique_value(input['type'], input_name)
147         setattr(interface.inputs, input_name, tempvalue)
148         input['tempvalue'] = tempvalue
149         if verbose:
150             print("oo Path-template creation using " + input['id'] + "=" +
151                   str(tempvalue))
152 
153     # Now that temp values have been generated, set Boolean types to
154     # Number (there is no Boolean type in Boutiques)
155     if input['type'] == "Boolean":
156         input['type'] = "Number"
157 
158     return input
159 
160 
161 def get_boutiques_output(name, interface, tool_inputs, verbose=False):
162     """
163     Returns a dictionary containing the Boutiques output corresponding to a Nipype output.
164 
165     Args:
166       * name: name of the Nipype output.
167       * interface: Nipype interface.
168       * tool_inputs: list of tool inputs (as produced by method get_boutiques_input).
169 
170     Assumes that:
171       * Output names are unique.
172       * Input values involved in the path template are defined.
173       * Output files are written in the current directory.
174       * There is a single output value (output lists are not supported).
175     """
176     output = {}
177     output['name'] = name.replace('_', ' ').capitalize()
178     output['id'] = name
179     output['type'] = "File"
180     output['path-template'] = ""
181     output[
182         'optional'] = True  # no real way to determine if an output is always produced, regardless of the input values.
183 
184     # Path template creation.
185 
186     output_value = interface._list_outputs()[name]
187     if output_value != "" and isinstance(
188             output_value,
189             str):  # FIXME: this crashes when there are multiple output values.
190         # Go find from which input value it was built
191         for input in tool_inputs:
192             if not input['tempvalue']:
193                 continue
194             input_value = input['tempvalue']
195             if input['type'] == "File":
196                 # Take the base name
197                 input_value = os.path.splitext(
198                     os.path.basename(input_value))[0]
199             if str(input_value) in output_value:
200                 output_value = os.path.basename(
201                     output_value.replace(input_value,
202                                          input['command-line-key'])
203                 )  # FIXME: this only works if output is written in the current directory
204         output['path-template'] = os.path.basename(output_value)
205     return output
206 
207 
208 def get_type_from_spec_info(spec_info):
209     '''
210     Returns an input type from the spec info. There must be a better
211     way to get an input type in Nipype than to parse the spec info.
212     '''
213     if ("an existing file name" in spec_info) or (
214             "input volumes" in spec_info):
215         return "File"
216     elif ("an integer" in spec_info or "a float" in spec_info):
217         return "Number"
218     elif "a boolean" in spec_info:
219         return "Boolean"
220     return "String"
221 
222 
223 def is_list(spec_info):
224     '''
225     Returns True if the spec info looks like it describes a list
226     parameter. There must be a better way in Nipype to check if an input
227     is a list.
228     '''
229     if "a list" in spec_info:
230         return True
231     return False
232 
233 
234 def get_unique_value(type, id):
235     '''
236     Returns a unique value of type 'type', for input with id 'id',
237     assuming id is unique.
238     '''
239     return {
240         "File": os.path.abspath(create_tempfile()),
241         "Boolean": True,
242         "Number": abs(hash(id)),  # abs in case input param must be positive...
243         "String": id
244     }[type]
245 
246 
247 def create_tempfile():
248     '''
249     Creates a temp file and returns its name.
250     '''
251     fileTemp = tempfile.NamedTemporaryFile(delete=False)
252     fileTemp.write("hello")
253     fileTemp.close()
254     return fileTemp.name
255 
256 
257 def must_generate_value(name, type, ignored_template_inputs, spec_info, spec,
258                         ignore_template_numbers):
259     '''
260     Return True if a temporary value must be generated for this input.
261     Arguments:
262     * name: input name.
263     * type: input_type.
264     * ignored_template_inputs: a list of inputs names for which no value must be generated.
265     * spec_info: spec info of the Nipype input
266     * ignore_template_numbers: True if numbers must be ignored.
267     '''
268     # Return false when type is number and numbers must be ignored.
269     if ignore_template_numbers and type == "Number":
270         return False
271     # Only generate value for the first element of mutually exclusive inputs.
272     if spec.xor and spec.xor[0] != name:
273         return False
274     # Directory types are not supported
275     if "an existing directory name" in spec_info:
276         return False
277     # Don't know how to generate a list.
278     if "a list" in spec_info or "a tuple" in spec_info:
279         return False
280     # Don't know how to generate a dictionary.
281     if "a dictionary" in spec_info:
282         return False
283     # Best guess to detect string restrictions...
284     if "' or '" in spec_info:
285         return False
286     if not ignored_template_inputs:
287         return True
288     return not (name in ignored_template_inputs)
289
```
--- 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/nipype/utils/nipype2boutiques.py b/nipype/utils/nipype2boutiques.py
--- a/nipype/utils/nipype2boutiques.py
+++ b/nipype/utils/nipype2boutiques.py
@@ -2,7 +2,7 @@
 from __future__ import (print_function, division, unicode_literals,
                         absolute_import)
 
-from builtins import str, open
+from builtins import str, open, bytes
 # This tool exports a Nipype interface in the Boutiques (https://github.com/boutiques) JSON format.
 # Boutiques tools can be imported in CBRAIN (https://github.com/aces/cbrain) among other platforms.
 #
@@ -40,10 +40,12 @@
         raise Exception("Undefined module.")
 
     # Retrieves Nipype interface
-    if isinstance(module, str):
+    if isinstance(module, (str, bytes)):
         import_module(module)
         module_name = str(module)
         module = sys.modules[module]
+    else:
+        module_name = str(module.__name__)
 
     interface = getattr(module, interface_name)()
     inputs = interface.input_spec()
@@ -249,7 +251,7 @@
     Creates a temp file and returns its name.
     '''
     fileTemp = tempfile.NamedTemporaryFile(delete=False)
-    fileTemp.write("hello")
+    fileTemp.write(b"hello")
     fileTemp.close()
     return fileTemp.name
 
@@ -283,6 +285,8 @@
     # Best guess to detect string restrictions...
     if "' or '" in spec_info:
         return False
+    if spec.default or spec.default_value():
+        return False
     if not ignored_template_inputs:
         return True
     return not (name in ignored_template_inputs)

{"golden_diff": "diff --git a/nipype/utils/nipype2boutiques.py b/nipype/utils/nipype2boutiques.py\n--- a/nipype/utils/nipype2boutiques.py\n+++ b/nipype/utils/nipype2boutiques.py\n@@ -2,7 +2,7 @@\n from __future__ import (print_function, division, unicode_literals,\n                         absolute_import)\n \n-from builtins import str, open\n+from builtins import str, open, bytes\n # This tool exports a Nipype interface in the Boutiques (https://github.com/boutiques) JSON format.\n # Boutiques tools can be imported in CBRAIN (https://github.com/aces/cbrain) among other platforms.\n #\n@@ -40,10 +40,12 @@\n         raise Exception(\"Undefined module.\")\n \n     # Retrieves Nipype interface\n-    if isinstance(module, str):\n+    if isinstance(module, (str, bytes)):\n         import_module(module)\n         module_name = str(module)\n         module = sys.modules[module]\n+    else:\n+        module_name = str(module.__name__)\n \n     interface = getattr(module, interface_name)()\n     inputs = interface.input_spec()\n@@ -249,7 +251,7 @@\n     Creates a temp file and returns its name.\n     '''\n     fileTemp = tempfile.NamedTemporaryFile(delete=False)\n-    fileTemp.write(\"hello\")\n+    fileTemp.write(b\"hello\")\n     fileTemp.close()\n     return fileTemp.name\n \n@@ -283,6 +285,8 @@\n     # Best guess to detect string restrictions...\n     if \"' or '\" in spec_info:\n         return False\n+    if spec.default or spec.default_value():\n+        return False\n     if not ignored_template_inputs:\n         return True\n     return not (name in ignored_template_inputs)\n", "issue": "UnboundLocalError: local variable 'module_name' referenced before assignment\n### Summary\r\nDiscovered for myself `nipypecli` and decided to give it a try while composing cmdline invocation just following the errors it was spitting out at me and stopping when error didn't give a hint what I could have specified incorrectly:\r\n\r\n```\r\n$> nipypecli convert boutiques -m nipype.interfaces.ants.registration -i ANTS -o test\r\nTraceback (most recent call last):\r\n  File \"/usr/bin/nipypecli\", line 11, in <module>\r\n    load_entry_point('nipype==1.0.1', 'console_scripts', 'nipypecli')()\r\n  File \"/usr/lib/python2.7/dist-packages/click/core.py\", line 722, in __call__\r\n    return self.main(*args, **kwargs)\r\n  File \"/usr/lib/python2.7/dist-packages/click/core.py\", line 697, in main\r\n    rv = self.invoke(ctx)\r\n  File \"/usr/lib/python2.7/dist-packages/click/core.py\", line 1066, in invoke\r\n    return _process_result(sub_ctx.command.invoke(sub_ctx))\r\n  File \"/usr/lib/python2.7/dist-packages/click/core.py\", line 1066, in invoke\r\n    return _process_result(sub_ctx.command.invoke(sub_ctx))\r\n  File \"/usr/lib/python2.7/dist-packages/click/core.py\", line 895, in invoke\r\n    return ctx.invoke(self.callback, **ctx.params)\r\n  File \"/usr/lib/python2.7/dist-packages/click/core.py\", line 535, in invoke\r\n    return callback(*args, **kwargs)\r\n  File \"/usr/lib/python2.7/dist-packages/nipype/scripts/cli.py\", line 254, in boutiques\r\n    verbose, ignore_template_numbers)\r\n  File \"/usr/lib/python2.7/dist-packages/nipype/utils/nipype2boutiques.py\", line 56, in generate_boutiques_descriptor\r\n    'command-line'] = \"nipype_cmd \" + module_name + \" \" + interface_name + \" \"\r\nUnboundLocalError: local variable 'module_name' referenced before assignment\r\n```\r\n\n", "before_files": [{"content": "# -*- coding: utf-8 -*-\nfrom __future__ import (print_function, division, unicode_literals,\n                        absolute_import)\n\nfrom builtins import str, open\n# This tool exports a Nipype interface in the Boutiques (https://github.com/boutiques) JSON format.\n# Boutiques tools can be imported in CBRAIN (https://github.com/aces/cbrain) among other platforms.\n#\n# Limitations:\n#   * List outputs are not supported.\n#   * Default values are not extracted from the documentation of the Nipype interface.\n#   * The following input types must be ignored for the output path template creation (see option -t):\n#     ** String restrictions, i.e. String inputs that accept only a restricted set of values.\n#     ** mutually exclusive inputs.\n#   * Path-templates are wrong when output files are not created in the execution directory (e.g. when a sub-directory is created).\n#   * Optional outputs, i.e. outputs that not always produced, may not be detected.\n\nimport os\nimport argparse\nimport sys\nimport tempfile\nimport simplejson as json\n\nfrom ..scripts.instance import import_module\n\n\ndef generate_boutiques_descriptor(\n        module, interface_name, ignored_template_inputs, docker_image,\n        docker_index, verbose, ignore_template_numbers):\n    '''\n    Returns a JSON string containing a JSON Boutiques description of a Nipype interface.\n    Arguments:\n    * module: module where the Nipype interface is declared.\n    * interface: Nipype interface.\n    * ignored_template_inputs: a list of input names that should be ignored in the generation of output path templates.\n    * ignore_template_numbers: True if numbers must be ignored in output path creations.\n    '''\n\n    if not module:\n        raise Exception(\"Undefined module.\")\n\n    # Retrieves Nipype interface\n    if isinstance(module, str):\n        import_module(module)\n        module_name = str(module)\n        module = sys.modules[module]\n\n    interface = getattr(module, interface_name)()\n    inputs = interface.input_spec()\n    outputs = interface.output_spec()\n\n    # Tool description\n    tool_desc = {}\n    tool_desc['name'] = interface_name\n    tool_desc[\n        'command-line'] = \"nipype_cmd \" + module_name + \" \" + interface_name + \" \"\n    tool_desc[\n        'description'] = interface_name + \", as implemented in Nipype (module: \" + module_name + \", interface: \" + interface_name + \").\"\n    tool_desc['inputs'] = []\n    tool_desc['outputs'] = []\n    tool_desc['tool-version'] = interface.version\n    tool_desc['schema-version'] = '0.2-snapshot'\n    if docker_image:\n        tool_desc['docker-image'] = docker_image\n    if docker_index:\n        tool_desc['docker-index'] = docker_index\n\n    # Generates tool inputs\n    for name, spec in sorted(interface.inputs.traits(transient=None).items()):\n        input = get_boutiques_input(inputs, interface, name, spec,\n                                    ignored_template_inputs, verbose,\n                                    ignore_template_numbers)\n        tool_desc['inputs'].append(input)\n        tool_desc['command-line'] += input['command-line-key'] + \" \"\n        if verbose:\n            print(\"-> Adding input \" + input['name'])\n\n    # Generates tool outputs\n    for name, spec in sorted(outputs.traits(transient=None).items()):\n        output = get_boutiques_output(name, interface, tool_desc['inputs'],\n                                      verbose)\n        if output['path-template'] != \"\":\n            tool_desc['outputs'].append(output)\n            if verbose:\n                print(\"-> Adding output \" + output['name'])\n        elif verbose:\n            print(\"xx Skipping output \" + output['name'] +\n                  \" with no path template.\")\n    if tool_desc['outputs'] == []:\n        raise Exception(\"Tool has no output.\")\n\n    # Removes all temporary values from inputs (otherwise they will\n    # appear in the JSON output)\n    for input in tool_desc['inputs']:\n        del input['tempvalue']\n\n    return json.dumps(tool_desc, indent=4, separators=(',', ': '))\n\n\ndef get_boutiques_input(inputs, interface, input_name, spec,\n                        ignored_template_inputs, verbose,\n                        ignore_template_numbers):\n    \"\"\"\n    Returns a dictionary containing the Boutiques input corresponding to a Nipype intput.\n\n    Args:\n      * inputs: inputs of the Nipype interface.\n      * interface: Nipype interface.\n      * input_name: name of the Nipype input.\n      * spec: Nipype input spec.\n      * ignored_template_inputs: input names for which no temporary value must be generated.\n      * ignore_template_numbers: True if numbers must be ignored in output path creations.\n\n    Assumes that:\n      * Input names are unique.\n    \"\"\"\n    if not spec.desc:\n        spec.desc = \"No description provided.\"\n    spec_info = spec.full_info(inputs, input_name, None)\n\n    input = {}\n    input['id'] = input_name\n    input['name'] = input_name.replace('_', ' ').capitalize()\n    input['type'] = get_type_from_spec_info(spec_info)\n    input['list'] = is_list(spec_info)\n    input['command-line-key'] = \"[\" + input_name.upper(\n    ) + \"]\"  # assumes that input names are unique\n    input['command-line-flag'] = (\"--%s\" % input_name + \" \").strip()\n    input['tempvalue'] = None\n    input['description'] = spec_info.capitalize(\n    ) + \". \" + spec.desc.capitalize()\n    if not input['description'].endswith('.'):\n        input['description'] += '.'\n    if not (hasattr(spec, \"mandatory\") and spec.mandatory):\n        input['optional'] = True\n    else:\n        input['optional'] = False\n    if spec.usedefault:\n        input['default-value'] = spec.default_value()[1]\n\n    # Create unique, temporary value.\n    temp_value = must_generate_value(input_name, input['type'],\n                                     ignored_template_inputs, spec_info, spec,\n                                     ignore_template_numbers)\n    if temp_value:\n        tempvalue = get_unique_value(input['type'], input_name)\n        setattr(interface.inputs, input_name, tempvalue)\n        input['tempvalue'] = tempvalue\n        if verbose:\n            print(\"oo Path-template creation using \" + input['id'] + \"=\" +\n                  str(tempvalue))\n\n    # Now that temp values have been generated, set Boolean types to\n    # Number (there is no Boolean type in Boutiques)\n    if input['type'] == \"Boolean\":\n        input['type'] = \"Number\"\n\n    return input\n\n\ndef get_boutiques_output(name, interface, tool_inputs, verbose=False):\n    \"\"\"\n    Returns a dictionary containing the Boutiques output corresponding to a Nipype output.\n\n    Args:\n      * name: name of the Nipype output.\n      * interface: Nipype interface.\n      * tool_inputs: list of tool inputs (as produced by method get_boutiques_input).\n\n    Assumes that:\n      * Output names are unique.\n      * Input values involved in the path template are defined.\n      * Output files are written in the current directory.\n      * There is a single output value (output lists are not supported).\n    \"\"\"\n    output = {}\n    output['name'] = name.replace('_', ' ').capitalize()\n    output['id'] = name\n    output['type'] = \"File\"\n    output['path-template'] = \"\"\n    output[\n        'optional'] = True  # no real way to determine if an output is always produced, regardless of the input values.\n\n    # Path template creation.\n\n    output_value = interface._list_outputs()[name]\n    if output_value != \"\" and isinstance(\n            output_value,\n            str):  # FIXME: this crashes when there are multiple output values.\n        # Go find from which input value it was built\n        for input in tool_inputs:\n            if not input['tempvalue']:\n                continue\n            input_value = input['tempvalue']\n            if input['type'] == \"File\":\n                # Take the base name\n                input_value = os.path.splitext(\n                    os.path.basename(input_value))[0]\n            if str(input_value) in output_value:\n                output_value = os.path.basename(\n                    output_value.replace(input_value,\n                                         input['command-line-key'])\n                )  # FIXME: this only works if output is written in the current directory\n        output['path-template'] = os.path.basename(output_value)\n    return output\n\n\ndef get_type_from_spec_info(spec_info):\n    '''\n    Returns an input type from the spec info. There must be a better\n    way to get an input type in Nipype than to parse the spec info.\n    '''\n    if (\"an existing file name\" in spec_info) or (\n            \"input volumes\" in spec_info):\n        return \"File\"\n    elif (\"an integer\" in spec_info or \"a float\" in spec_info):\n        return \"Number\"\n    elif \"a boolean\" in spec_info:\n        return \"Boolean\"\n    return \"String\"\n\n\ndef is_list(spec_info):\n    '''\n    Returns True if the spec info looks like it describes a list\n    parameter. There must be a better way in Nipype to check if an input\n    is a list.\n    '''\n    if \"a list\" in spec_info:\n        return True\n    return False\n\n\ndef get_unique_value(type, id):\n    '''\n    Returns a unique value of type 'type', for input with id 'id',\n    assuming id is unique.\n    '''\n    return {\n        \"File\": os.path.abspath(create_tempfile()),\n        \"Boolean\": True,\n        \"Number\": abs(hash(id)),  # abs in case input param must be positive...\n        \"String\": id\n    }[type]\n\n\ndef create_tempfile():\n    '''\n    Creates a temp file and returns its name.\n    '''\n    fileTemp = tempfile.NamedTemporaryFile(delete=False)\n    fileTemp.write(\"hello\")\n    fileTemp.close()\n    return fileTemp.name\n\n\ndef must_generate_value(name, type, ignored_template_inputs, spec_info, spec,\n                        ignore_template_numbers):\n    '''\n    Return True if a temporary value must be generated for this input.\n    Arguments:\n    * name: input name.\n    * type: input_type.\n    * ignored_template_inputs: a list of inputs names for which no value must be generated.\n    * spec_info: spec info of the Nipype input\n    * ignore_template_numbers: True if numbers must be ignored.\n    '''\n    # Return false when type is number and numbers must be ignored.\n    if ignore_template_numbers and type == \"Number\":\n        return False\n    # Only generate value for the first element of mutually exclusive inputs.\n    if spec.xor and spec.xor[0] != name:\n        return False\n    # Directory types are not supported\n    if \"an existing directory name\" in spec_info:\n        return False\n    # Don't know how to generate a list.\n    if \"a list\" in spec_info or \"a tuple\" in spec_info:\n        return False\n    # Don't know how to generate a dictionary.\n    if \"a dictionary\" in spec_info:\n        return False\n    # Best guess to detect string restrictions...\n    if \"' or '\" in spec_info:\n        return False\n    if not ignored_template_inputs:\n        return True\n    return not (name in ignored_template_inputs)\n", "path": "nipype/utils/nipype2boutiques.py"}], "after_files": [{"content": "# -*- coding: utf-8 -*-\nfrom __future__ import (print_function, division, unicode_literals,\n                        absolute_import)\n\nfrom builtins import str, open, bytes\n# This tool exports a Nipype interface in the Boutiques (https://github.com/boutiques) JSON format.\n# Boutiques tools can be imported in CBRAIN (https://github.com/aces/cbrain) among other platforms.\n#\n# Limitations:\n#   * List outputs are not supported.\n#   * Default values are not extracted from the documentation of the Nipype interface.\n#   * The following input types must be ignored for the output path template creation (see option -t):\n#     ** String restrictions, i.e. String inputs that accept only a restricted set of values.\n#     ** mutually exclusive inputs.\n#   * Path-templates are wrong when output files are not created in the execution directory (e.g. when a sub-directory is created).\n#   * Optional outputs, i.e. outputs that not always produced, may not be detected.\n\nimport os\nimport argparse\nimport sys\nimport tempfile\nimport simplejson as json\n\nfrom ..scripts.instance import import_module\n\n\ndef generate_boutiques_descriptor(\n        module, interface_name, ignored_template_inputs, docker_image,\n        docker_index, verbose, ignore_template_numbers):\n    '''\n    Returns a JSON string containing a JSON Boutiques description of a Nipype interface.\n    Arguments:\n    * module: module where the Nipype interface is declared.\n    * interface: Nipype interface.\n    * ignored_template_inputs: a list of input names that should be ignored in the generation of output path templates.\n    * ignore_template_numbers: True if numbers must be ignored in output path creations.\n    '''\n\n    if not module:\n        raise Exception(\"Undefined module.\")\n\n    # Retrieves Nipype interface\n    if isinstance(module, (str, bytes)):\n        import_module(module)\n        module_name = str(module)\n        module = sys.modules[module]\n    else:\n        module_name = str(module.__name__)\n\n    interface = getattr(module, interface_name)()\n    inputs = interface.input_spec()\n    outputs = interface.output_spec()\n\n    # Tool description\n    tool_desc = {}\n    tool_desc['name'] = interface_name\n    tool_desc[\n        'command-line'] = \"nipype_cmd \" + module_name + \" \" + interface_name + \" \"\n    tool_desc[\n        'description'] = interface_name + \", as implemented in Nipype (module: \" + module_name + \", interface: \" + interface_name + \").\"\n    tool_desc['inputs'] = []\n    tool_desc['outputs'] = []\n    tool_desc['tool-version'] = interface.version\n    tool_desc['schema-version'] = '0.2-snapshot'\n    if docker_image:\n        tool_desc['docker-image'] = docker_image\n    if docker_index:\n        tool_desc['docker-index'] = docker_index\n\n    # Generates tool inputs\n    for name, spec in sorted(interface.inputs.traits(transient=None).items()):\n        input = get_boutiques_input(inputs, interface, name, spec,\n                                    ignored_template_inputs, verbose,\n                                    ignore_template_numbers)\n        tool_desc['inputs'].append(input)\n        tool_desc['command-line'] += input['command-line-key'] + \" \"\n        if verbose:\n            print(\"-> Adding input \" + input['name'])\n\n    # Generates tool outputs\n    for name, spec in sorted(outputs.traits(transient=None).items()):\n        output = get_boutiques_output(name, interface, tool_desc['inputs'],\n                                      verbose)\n        if output['path-template'] != \"\":\n            tool_desc['outputs'].append(output)\n            if verbose:\n                print(\"-> Adding output \" + output['name'])\n        elif verbose:\n            print(\"xx Skipping output \" + output['name'] +\n                  \" with no path template.\")\n    if tool_desc['outputs'] == []:\n        raise Exception(\"Tool has no output.\")\n\n    # Removes all temporary values from inputs (otherwise they will\n    # appear in the JSON output)\n    for input in tool_desc['inputs']:\n        del input['tempvalue']\n\n    return json.dumps(tool_desc, indent=4, separators=(',', ': '))\n\n\ndef get_boutiques_input(inputs, interface, input_name, spec,\n                        ignored_template_inputs, verbose,\n                        ignore_template_numbers):\n    \"\"\"\n    Returns a dictionary containing the Boutiques input corresponding to a Nipype intput.\n\n    Args:\n      * inputs: inputs of the Nipype interface.\n      * interface: Nipype interface.\n      * input_name: name of the Nipype input.\n      * spec: Nipype input spec.\n      * ignored_template_inputs: input names for which no temporary value must be generated.\n      * ignore_template_numbers: True if numbers must be ignored in output path creations.\n\n    Assumes that:\n      * Input names are unique.\n    \"\"\"\n    if not spec.desc:\n        spec.desc = \"No description provided.\"\n    spec_info = spec.full_info(inputs, input_name, None)\n\n    input = {}\n    input['id'] = input_name\n    input['name'] = input_name.replace('_', ' ').capitalize()\n    input['type'] = get_type_from_spec_info(spec_info)\n    input['list'] = is_list(spec_info)\n    input['command-line-key'] = \"[\" + input_name.upper(\n    ) + \"]\"  # assumes that input names are unique\n    input['command-line-flag'] = (\"--%s\" % input_name + \" \").strip()\n    input['tempvalue'] = None\n    input['description'] = spec_info.capitalize(\n    ) + \". \" + spec.desc.capitalize()\n    if not input['description'].endswith('.'):\n        input['description'] += '.'\n    if not (hasattr(spec, \"mandatory\") and spec.mandatory):\n        input['optional'] = True\n    else:\n        input['optional'] = False\n    if spec.usedefault:\n        input['default-value'] = spec.default_value()[1]\n\n    # Create unique, temporary value.\n    temp_value = must_generate_value(input_name, input['type'],\n                                     ignored_template_inputs, spec_info, spec,\n                                     ignore_template_numbers)\n    if temp_value:\n        tempvalue = get_unique_value(input['type'], input_name)\n        setattr(interface.inputs, input_name, tempvalue)\n        input['tempvalue'] = tempvalue\n        if verbose:\n            print(\"oo Path-template creation using \" + input['id'] + \"=\" +\n                  str(tempvalue))\n\n    # Now that temp values have been generated, set Boolean types to\n    # Number (there is no Boolean type in Boutiques)\n    if input['type'] == \"Boolean\":\n        input['type'] = \"Number\"\n\n    return input\n\n\ndef get_boutiques_output(name, interface, tool_inputs, verbose=False):\n    \"\"\"\n    Returns a dictionary containing the Boutiques output corresponding to a Nipype output.\n\n    Args:\n      * name: name of the Nipype output.\n      * interface: Nipype interface.\n      * tool_inputs: list of tool inputs (as produced by method get_boutiques_input).\n\n    Assumes that:\n      * Output names are unique.\n      * Input values involved in the path template are defined.\n      * Output files are written in the current directory.\n      * There is a single output value (output lists are not supported).\n    \"\"\"\n    output = {}\n    output['name'] = name.replace('_', ' ').capitalize()\n    output['id'] = name\n    output['type'] = \"File\"\n    output['path-template'] = \"\"\n    output[\n        'optional'] = True  # no real way to determine if an output is always produced, regardless of the input values.\n\n    # Path template creation.\n\n    output_value = interface._list_outputs()[name]\n    if output_value != \"\" and isinstance(\n            output_value,\n            str):  # FIXME: this crashes when there are multiple output values.\n        # Go find from which input value it was built\n        for input in tool_inputs:\n            if not input['tempvalue']:\n                continue\n            input_value = input['tempvalue']\n            if input['type'] == \"File\":\n                # Take the base name\n                input_value = os.path.splitext(\n                    os.path.basename(input_value))[0]\n            if str(input_value) in output_value:\n                output_value = os.path.basename(\n                    output_value.replace(input_value,\n                                         input['command-line-key'])\n                )  # FIXME: this only works if output is written in the current directory\n        output['path-template'] = os.path.basename(output_value)\n    return output\n\n\ndef get_type_from_spec_info(spec_info):\n    '''\n    Returns an input type from the spec info. There must be a better\n    way to get an input type in Nipype than to parse the spec info.\n    '''\n    if (\"an existing file name\" in spec_info) or (\n            \"input volumes\" in spec_info):\n        return \"File\"\n    elif (\"an integer\" in spec_info or \"a float\" in spec_info):\n        return \"Number\"\n    elif \"a boolean\" in spec_info:\n        return \"Boolean\"\n    return \"String\"\n\n\ndef is_list(spec_info):\n    '''\n    Returns True if the spec info looks like it describes a list\n    parameter. There must be a better way in Nipype to check if an input\n    is a list.\n    '''\n    if \"a list\" in spec_info:\n        return True\n    return False\n\n\ndef get_unique_value(type, id):\n    '''\n    Returns a unique value of type 'type', for input with id 'id',\n    assuming id is unique.\n    '''\n    return {\n        \"File\": os.path.abspath(create_tempfile()),\n        \"Boolean\": True,\n        \"Number\": abs(hash(id)),  # abs in case input param must be positive...\n        \"String\": id\n    }[type]\n\n\ndef create_tempfile():\n    '''\n    Creates a temp file and returns its name.\n    '''\n    fileTemp = tempfile.NamedTemporaryFile(delete=False)\n    fileTemp.write(b\"hello\")\n    fileTemp.close()\n    return fileTemp.name\n\n\ndef must_generate_value(name, type, ignored_template_inputs, spec_info, spec,\n                        ignore_template_numbers):\n    '''\n    Return True if a temporary value must be generated for this input.\n    Arguments:\n    * name: input name.\n    * type: input_type.\n    * ignored_template_inputs: a list of inputs names for which no value must be generated.\n    * spec_info: spec info of the Nipype input\n    * ignore_template_numbers: True if numbers must be ignored.\n    '''\n    # Return false when type is number and numbers must be ignored.\n    if ignore_template_numbers and type == \"Number\":\n        return False\n    # Only generate value for the first element of mutually exclusive inputs.\n    if spec.xor and spec.xor[0] != name:\n        return False\n    # Directory types are not supported\n    if \"an existing directory name\" in spec_info:\n        return False\n    # Don't know how to generate a list.\n    if \"a list\" in spec_info or \"a tuple\" in spec_info:\n        return False\n    # Don't know how to generate a dictionary.\n    if \"a dictionary\" in spec_info:\n        return False\n    # Best guess to detect string restrictions...\n    if \"' or '\" in spec_info:\n        return False\n    if spec.default or spec.default_value():\n        return False\n    if not ignored_template_inputs:\n        return True\n    return not (name in ignored_template_inputs)\n", "path": "nipype/utils/nipype2boutiques.py"}]}