We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Logger adding extra lines, prefixing them with -->
logger.warning now appends --> to every line. This causes the output of things like ansible-playbook to have normally blank lines prefixed with -->, causing a lot of extra noise during a converge.  The _out for the sh calls to various programs doesn't need anything appended to it. @kireledan 

<img width="986" alt="screen shot 2016-06-28 at 1 41 48 pm" src="https://cloud.githubusercontent.com/assets/5855384/16429848/1adebbcc-3d36-11e6-832b-4911c8db26dd.png">


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `molecule/utilities.py`
Content:
```
1 #  Copyright (c) 2015 Cisco Systems
2 #
3 #  Permission is hereby granted, free of charge, to any person obtaining a copy
4 #  of this software and associated documentation files (the "Software"), to deal
5 #  in the Software without restriction, including without limitation the rights
6 #  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 #  copies of the Software, and to permit persons to whom the Software is
8 #  furnished to do so, subject to the following conditions:
9 #
10 #  The above copyright notice and this permission notice shall be included in
11 #  all copies or substantial portions of the Software.
12 #
13 #  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 #  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 #  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 #  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 #  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 #  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 #  THE SOFTWARE.
20 
21 from __future__ import print_function
22 
23 import copy
24 import os
25 import sys
26 
27 import logging
28 
29 import colorama
30 import jinja2
31 
32 
33 class LogFilter(object):
34     def __init__(self, level):
35         self.__level = level
36 
37     def filter(self, logRecord):
38         return logRecord.levelno <= self.__level
39 
40 
41 logger = logging.getLogger(__name__)
42 warn = logging.StreamHandler()
43 warn.setLevel(logging.WARN)
44 warn.addFilter(LogFilter(logging.WARN))
45 warn.setFormatter(logging.Formatter('{}{} --> {}{} %(message)s'.format(
46     colorama.Style.BRIGHT, colorama.Fore.BLUE, colorama.Fore.RESET,
47     colorama.Style.RESET_ALL)))
48 
49 error = logging.StreamHandler()
50 error.setLevel(logging.ERROR)
51 error.setFormatter(logging.Formatter('{}{} --> {}{} %(message)s'.format(
52     colorama.Style.BRIGHT, colorama.Fore.RED, colorama.Fore.RESET,
53     colorama.Style.RESET_ALL)))
54 logger.addHandler(error)
55 logger.addHandler(warn)
56 
57 
58 def merge_dicts(a, b, raise_conflicts=False, path=None):
59     """
60     Merges the values of B into A.
61     If the raise_conflicts flag is set to True, a LookupError will be raised if the keys are conflicting.
62     :param a: the target dictionary
63     :param b: the dictionary to import
64     :param raise_conflicts: flag to raise an exception if two keys are colliding
65     :param path: the dictionary path. Used to show where the keys are conflicting when an exception is raised.
66     :return: The dictionary A with the values of the dictionary B merged into it.
67     """
68     # Set path.
69     if path is None:
70         path = []
71 
72     # Go through the keys of the 2 dictionaries.
73     for key in b:
74         # If the key exist in both dictionary, check whether we must update or not.
75         if key in a:
76             # Dig deeper for keys that have dictionary values.
77             if isinstance(a[key], dict) and isinstance(b[key], dict):
78                 merge_dicts(a[key],
79                             b[key],
80                             raise_conflicts=raise_conflicts,
81                             path=(path + [str(key)]))
82 
83             # Skip the identical values.
84             elif a[key] == b[key]:
85                 pass
86             else:
87                 # Otherwise raise an error if the same keys have different values.
88                 if raise_conflicts:
89                     raise LookupError("Conflict at '{path}'".format(
90                         path='.'.join(path + [str(key)])))
91 
92                 # Or replace the value of A with the value of B.
93                 a[key] = b[key]
94         else:
95             # If the key does not exist in A, import it.
96             a[key] = copy.deepcopy(b[key]) if isinstance(b[key],
97                                                          dict) else b[key]
98 
99     return a
100 
101 
102 def write_template(src, dest, kwargs={}, _module='molecule', _dir='templates'):
103     """
104     Writes a file from a jinja2 template.
105     :param src: the target template files to use
106     :param dest: destination of the templatized file to be written
107     :param kwargs: dictionary of arguments passed to jinja2 when rendering template
108     :param _module: module (to look for template files) passed to jinja2 PackageLoader
109     :param _dir: directory (to look for template files) passed to jinja2 PackageLoader
110     :return: None
111     """
112     src = os.path.expanduser(src)
113     path = os.path.dirname(src)
114     filename = os.path.basename(src)
115 
116     # template file doesn't exist
117     if path and not os.path.isfile(src):
118         logger.error('\n{}Unable to locate template file: {}{}'.format(
119             colorama.Fore.RED, src, colorama.Fore.RESET))
120         sys.exit(1)
121 
122     # look for template in filesystem, then molecule package
123     loader = jinja2.ChoiceLoader([jinja2.FileSystemLoader(path,
124                                                           followlinks=True),
125                                   jinja2.PackageLoader(_module, _dir)])
126 
127     env = jinja2.Environment(loader=loader)
128     template = env.get_template(filename)
129 
130     with open(dest, 'w') as f:
131         f.write(template.render(**kwargs))
132 
133 
134 def write_file(filename, content):
135     """
136     Writes a file with the given filename using the given content. Overwrites, does not append.
137     :param filename: the target filename
138     :param content: what gets written into the file
139     :return: None
140     """
141     with open(filename, 'w') as f:
142         f.write(content)
143 
144 
145 def format_instance_name(name, platform, instances):
146     """
147     Takes an instance name and formats it according to options specified in the instance's config.
148     :param name: the name of the instance
149     :param platform: the current molecule platform in use
150     :param instances: the current molecule instances dict in use
151     :return: formatted instance name if found in instances, otherwise None
152     """
153     working_instance = None
154 
155     # search instances for given name
156     for instance in instances:
157         if instance['name'] == name:
158             working_instance = instance
159             break
160 
161     # no instance found with given name
162     if working_instance is None:
163         return
164 
165     # return the default name if no options are specified for instance
166     if working_instance.get('options') is None:
167         return name
168 
169     # add platform to name
170     if working_instance['options'].get('append_platform_to_hostname'):
171         return name + '-' + platform
172 
173     # if we fall through, return the default name
174     return name
175 
176 
177 def remove_args(command_args, args, kill):
178     """
179     Removes args so commands can be passed around easily.
180     :param command_args: list of command args from DocOpt
181     :param args: dict of arguments from DocOpt
182     :kill: list of args to remove from returned values
183     :return: pruned command_args list, pruned args dict
184     """
185 
186     new_args = {}
187     new_command_args = []
188     skip_next = False
189 
190     # remove killed command args and their adjacent items
191     for item in command_args:
192         if skip_next:
193             skip_next = False
194             continue
195         if item.lower() in kill:
196             skip_next = True
197             continue
198         new_command_args.append(item)
199 
200     # remove killed command args
201     for k, v in args.iteritems():
202         if k not in kill:
203             new_args[k] = v
204 
205     return new_command_args, new_args
206 
207 
208 def debug(title, data):
209     """
210     Prints colorized output for use when debugging portions of molecule.
211     :param title: title of debug output
212     :param data: data of debug output
213     :return: None
214     """
215     print(''.join([colorama.Back.WHITE, colorama.Style.BRIGHT,
216                    colorama.Fore.BLACK, 'DEBUG: ' + title, colorama.Fore.RESET,
217                    colorama.Back.RESET, colorama.Style.RESET_ALL]))
218     print(''.join([colorama.Fore.BLACK, colorama.Style.BRIGHT, data,
219                    colorama.Style.RESET_ALL, colorama.Fore.RESET]))
220
```
--- 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/molecule/utilities.py b/molecule/utilities.py
--- a/molecule/utilities.py
+++ b/molecule/utilities.py
@@ -38,19 +38,21 @@
         return logRecord.levelno <= self.__level
 
 
+class TrailingNewlineFormatter(logging.Formatter):
+    def format(self, record):
+        record.msg = record.msg.rstrip()
+        return super(TrailingNewlineFormatter, self).format(record)
+
+
 logger = logging.getLogger(__name__)
 warn = logging.StreamHandler()
 warn.setLevel(logging.WARN)
 warn.addFilter(LogFilter(logging.WARN))
-warn.setFormatter(logging.Formatter('{}{} --> {}{} %(message)s'.format(
-    colorama.Style.BRIGHT, colorama.Fore.BLUE, colorama.Fore.RESET,
-    colorama.Style.RESET_ALL)))
+warn.setFormatter(TrailingNewlineFormatter('%(message)s'))
 
 error = logging.StreamHandler()
 error.setLevel(logging.ERROR)
-error.setFormatter(logging.Formatter('{}{} --> {}{} %(message)s'.format(
-    colorama.Style.BRIGHT, colorama.Fore.RED, colorama.Fore.RESET,
-    colorama.Style.RESET_ALL)))
+error.setFormatter(TrailingNewlineFormatter('%(message)s'))
 logger.addHandler(error)
 logger.addHandler(warn)

{"golden_diff": "diff --git a/molecule/utilities.py b/molecule/utilities.py\n--- a/molecule/utilities.py\n+++ b/molecule/utilities.py\n@@ -38,19 +38,21 @@\n         return logRecord.levelno <= self.__level\n \n \n+class TrailingNewlineFormatter(logging.Formatter):\n+    def format(self, record):\n+        record.msg = record.msg.rstrip()\n+        return super(TrailingNewlineFormatter, self).format(record)\n+\n+\n logger = logging.getLogger(__name__)\n warn = logging.StreamHandler()\n warn.setLevel(logging.WARN)\n warn.addFilter(LogFilter(logging.WARN))\n-warn.setFormatter(logging.Formatter('{}{} --> {}{} %(message)s'.format(\n-    colorama.Style.BRIGHT, colorama.Fore.BLUE, colorama.Fore.RESET,\n-    colorama.Style.RESET_ALL)))\n+warn.setFormatter(TrailingNewlineFormatter('%(message)s'))\n \n error = logging.StreamHandler()\n error.setLevel(logging.ERROR)\n-error.setFormatter(logging.Formatter('{}{} --> {}{} %(message)s'.format(\n-    colorama.Style.BRIGHT, colorama.Fore.RED, colorama.Fore.RESET,\n-    colorama.Style.RESET_ALL)))\n+error.setFormatter(TrailingNewlineFormatter('%(message)s'))\n logger.addHandler(error)\n logger.addHandler(warn)\n", "issue": "Logger adding extra lines, prefixing them with -->\nlogger.warning now appends --> to every line. This causes the output of things like ansible-playbook to have normally blank lines prefixed with -->, causing a lot of extra noise during a converge.  The _out for the sh calls to various programs doesn't need anything appended to it. @kireledan \n\n<img width=\"986\" alt=\"screen shot 2016-06-28 at 1 41 48 pm\" src=\"https://cloud.githubusercontent.com/assets/5855384/16429848/1adebbcc-3d36-11e6-832b-4911c8db26dd.png\">\n\n", "before_files": [{"content": "#  Copyright (c) 2015 Cisco Systems\n#\n#  Permission is hereby granted, free of charge, to any person obtaining a copy\n#  of this software and associated documentation files (the \"Software\"), to deal\n#  in the Software without restriction, including without limitation the rights\n#  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n#  copies of the Software, and to permit persons to whom the Software is\n#  furnished to do so, subject to the following conditions:\n#\n#  The above copyright notice and this permission notice shall be included in\n#  all copies or substantial portions of the Software.\n#\n#  THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n#  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n#  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n#  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n#  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n#  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n#  THE SOFTWARE.\n\nfrom __future__ import print_function\n\nimport copy\nimport os\nimport sys\n\nimport logging\n\nimport colorama\nimport jinja2\n\n\nclass LogFilter(object):\n    def __init__(self, level):\n        self.__level = level\n\n    def filter(self, logRecord):\n        return logRecord.levelno <= self.__level\n\n\nlogger = logging.getLogger(__name__)\nwarn = logging.StreamHandler()\nwarn.setLevel(logging.WARN)\nwarn.addFilter(LogFilter(logging.WARN))\nwarn.setFormatter(logging.Formatter('{}{} --> {}{} %(message)s'.format(\n    colorama.Style.BRIGHT, colorama.Fore.BLUE, colorama.Fore.RESET,\n    colorama.Style.RESET_ALL)))\n\nerror = logging.StreamHandler()\nerror.setLevel(logging.ERROR)\nerror.setFormatter(logging.Formatter('{}{} --> {}{} %(message)s'.format(\n    colorama.Style.BRIGHT, colorama.Fore.RED, colorama.Fore.RESET,\n    colorama.Style.RESET_ALL)))\nlogger.addHandler(error)\nlogger.addHandler(warn)\n\n\ndef merge_dicts(a, b, raise_conflicts=False, path=None):\n    \"\"\"\n    Merges the values of B into A.\n    If the raise_conflicts flag is set to True, a LookupError will be raised if the keys are conflicting.\n    :param a: the target dictionary\n    :param b: the dictionary to import\n    :param raise_conflicts: flag to raise an exception if two keys are colliding\n    :param path: the dictionary path. Used to show where the keys are conflicting when an exception is raised.\n    :return: The dictionary A with the values of the dictionary B merged into it.\n    \"\"\"\n    # Set path.\n    if path is None:\n        path = []\n\n    # Go through the keys of the 2 dictionaries.\n    for key in b:\n        # If the key exist in both dictionary, check whether we must update or not.\n        if key in a:\n            # Dig deeper for keys that have dictionary values.\n            if isinstance(a[key], dict) and isinstance(b[key], dict):\n                merge_dicts(a[key],\n                            b[key],\n                            raise_conflicts=raise_conflicts,\n                            path=(path + [str(key)]))\n\n            # Skip the identical values.\n            elif a[key] == b[key]:\n                pass\n            else:\n                # Otherwise raise an error if the same keys have different values.\n                if raise_conflicts:\n                    raise LookupError(\"Conflict at '{path}'\".format(\n                        path='.'.join(path + [str(key)])))\n\n                # Or replace the value of A with the value of B.\n                a[key] = b[key]\n        else:\n            # If the key does not exist in A, import it.\n            a[key] = copy.deepcopy(b[key]) if isinstance(b[key],\n                                                         dict) else b[key]\n\n    return a\n\n\ndef write_template(src, dest, kwargs={}, _module='molecule', _dir='templates'):\n    \"\"\"\n    Writes a file from a jinja2 template.\n    :param src: the target template files to use\n    :param dest: destination of the templatized file to be written\n    :param kwargs: dictionary of arguments passed to jinja2 when rendering template\n    :param _module: module (to look for template files) passed to jinja2 PackageLoader\n    :param _dir: directory (to look for template files) passed to jinja2 PackageLoader\n    :return: None\n    \"\"\"\n    src = os.path.expanduser(src)\n    path = os.path.dirname(src)\n    filename = os.path.basename(src)\n\n    # template file doesn't exist\n    if path and not os.path.isfile(src):\n        logger.error('\\n{}Unable to locate template file: {}{}'.format(\n            colorama.Fore.RED, src, colorama.Fore.RESET))\n        sys.exit(1)\n\n    # look for template in filesystem, then molecule package\n    loader = jinja2.ChoiceLoader([jinja2.FileSystemLoader(path,\n                                                          followlinks=True),\n                                  jinja2.PackageLoader(_module, _dir)])\n\n    env = jinja2.Environment(loader=loader)\n    template = env.get_template(filename)\n\n    with open(dest, 'w') as f:\n        f.write(template.render(**kwargs))\n\n\ndef write_file(filename, content):\n    \"\"\"\n    Writes a file with the given filename using the given content. Overwrites, does not append.\n    :param filename: the target filename\n    :param content: what gets written into the file\n    :return: None\n    \"\"\"\n    with open(filename, 'w') as f:\n        f.write(content)\n\n\ndef format_instance_name(name, platform, instances):\n    \"\"\"\n    Takes an instance name and formats it according to options specified in the instance's config.\n    :param name: the name of the instance\n    :param platform: the current molecule platform in use\n    :param instances: the current molecule instances dict in use\n    :return: formatted instance name if found in instances, otherwise None\n    \"\"\"\n    working_instance = None\n\n    # search instances for given name\n    for instance in instances:\n        if instance['name'] == name:\n            working_instance = instance\n            break\n\n    # no instance found with given name\n    if working_instance is None:\n        return\n\n    # return the default name if no options are specified for instance\n    if working_instance.get('options') is None:\n        return name\n\n    # add platform to name\n    if working_instance['options'].get('append_platform_to_hostname'):\n        return name + '-' + platform\n\n    # if we fall through, return the default name\n    return name\n\n\ndef remove_args(command_args, args, kill):\n    \"\"\"\n    Removes args so commands can be passed around easily.\n    :param command_args: list of command args from DocOpt\n    :param args: dict of arguments from DocOpt\n    :kill: list of args to remove from returned values\n    :return: pruned command_args list, pruned args dict\n    \"\"\"\n\n    new_args = {}\n    new_command_args = []\n    skip_next = False\n\n    # remove killed command args and their adjacent items\n    for item in command_args:\n        if skip_next:\n            skip_next = False\n            continue\n        if item.lower() in kill:\n            skip_next = True\n            continue\n        new_command_args.append(item)\n\n    # remove killed command args\n    for k, v in args.iteritems():\n        if k not in kill:\n            new_args[k] = v\n\n    return new_command_args, new_args\n\n\ndef debug(title, data):\n    \"\"\"\n    Prints colorized output for use when debugging portions of molecule.\n    :param title: title of debug output\n    :param data: data of debug output\n    :return: None\n    \"\"\"\n    print(''.join([colorama.Back.WHITE, colorama.Style.BRIGHT,\n                   colorama.Fore.BLACK, 'DEBUG: ' + title, colorama.Fore.RESET,\n                   colorama.Back.RESET, colorama.Style.RESET_ALL]))\n    print(''.join([colorama.Fore.BLACK, colorama.Style.BRIGHT, data,\n                   colorama.Style.RESET_ALL, colorama.Fore.RESET]))\n", "path": "molecule/utilities.py"}], "after_files": [{"content": "#  Copyright (c) 2015 Cisco Systems\n#\n#  Permission is hereby granted, free of charge, to any person obtaining a copy\n#  of this software and associated documentation files (the \"Software\"), to deal\n#  in the Software without restriction, including without limitation the rights\n#  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n#  copies of the Software, and to permit persons to whom the Software is\n#  furnished to do so, subject to the following conditions:\n#\n#  The above copyright notice and this permission notice shall be included in\n#  all copies or substantial portions of the Software.\n#\n#  THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n#  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n#  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n#  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n#  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n#  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n#  THE SOFTWARE.\n\nfrom __future__ import print_function\n\nimport copy\nimport os\nimport sys\n\nimport logging\n\nimport colorama\nimport jinja2\n\n\nclass LogFilter(object):\n    def __init__(self, level):\n        self.__level = level\n\n    def filter(self, logRecord):\n        return logRecord.levelno <= self.__level\n\n\nclass TrailingNewlineFormatter(logging.Formatter):\n    def format(self, record):\n        record.msg = record.msg.rstrip()\n        return super(TrailingNewlineFormatter, self).format(record)\n\n\nlogger = logging.getLogger(__name__)\nwarn = logging.StreamHandler()\nwarn.setLevel(logging.WARN)\nwarn.addFilter(LogFilter(logging.WARN))\nwarn.setFormatter(TrailingNewlineFormatter('%(message)s'))\n\nerror = logging.StreamHandler()\nerror.setLevel(logging.ERROR)\nerror.setFormatter(TrailingNewlineFormatter('%(message)s'))\nlogger.addHandler(error)\nlogger.addHandler(warn)\n\n\ndef merge_dicts(a, b, raise_conflicts=False, path=None):\n    \"\"\"\n    Merges the values of B into A.\n    If the raise_conflicts flag is set to True, a LookupError will be raised if the keys are conflicting.\n    :param a: the target dictionary\n    :param b: the dictionary to import\n    :param raise_conflicts: flag to raise an exception if two keys are colliding\n    :param path: the dictionary path. Used to show where the keys are conflicting when an exception is raised.\n    :return: The dictionary A with the values of the dictionary B merged into it.\n    \"\"\"\n    # Set path.\n    if path is None:\n        path = []\n\n    # Go through the keys of the 2 dictionaries.\n    for key in b:\n        # If the key exist in both dictionary, check whether we must update or not.\n        if key in a:\n            # Dig deeper for keys that have dictionary values.\n            if isinstance(a[key], dict) and isinstance(b[key], dict):\n                merge_dicts(a[key],\n                            b[key],\n                            raise_conflicts=raise_conflicts,\n                            path=(path + [str(key)]))\n\n            # Skip the identical values.\n            elif a[key] == b[key]:\n                pass\n            else:\n                # Otherwise raise an error if the same keys have different values.\n                if raise_conflicts:\n                    raise LookupError(\"Conflict at '{path}'\".format(\n                        path='.'.join(path + [str(key)])))\n\n                # Or replace the value of A with the value of B.\n                a[key] = b[key]\n        else:\n            # If the key does not exist in A, import it.\n            a[key] = copy.deepcopy(b[key]) if isinstance(b[key],\n                                                         dict) else b[key]\n\n    return a\n\n\ndef write_template(src, dest, kwargs={}, _module='molecule', _dir='templates'):\n    \"\"\"\n    Writes a file from a jinja2 template.\n    :param src: the target template files to use\n    :param dest: destination of the templatized file to be written\n    :param kwargs: dictionary of arguments passed to jinja2 when rendering template\n    :param _module: module (to look for template files) passed to jinja2 PackageLoader\n    :param _dir: directory (to look for template files) passed to jinja2 PackageLoader\n    :return: None\n    \"\"\"\n    src = os.path.expanduser(src)\n    path = os.path.dirname(src)\n    filename = os.path.basename(src)\n\n    # template file doesn't exist\n    if path and not os.path.isfile(src):\n        logger.error('\\n{}Unable to locate template file: {}{}'.format(\n            colorama.Fore.RED, src, colorama.Fore.RESET))\n        sys.exit(1)\n\n    # look for template in filesystem, then molecule package\n    loader = jinja2.ChoiceLoader([jinja2.FileSystemLoader(path,\n                                                          followlinks=True),\n                                  jinja2.PackageLoader(_module, _dir)])\n\n    env = jinja2.Environment(loader=loader)\n    template = env.get_template(filename)\n\n    with open(dest, 'w') as f:\n        f.write(template.render(**kwargs))\n\n\ndef write_file(filename, content):\n    \"\"\"\n    Writes a file with the given filename using the given content. Overwrites, does not append.\n    :param filename: the target filename\n    :param content: what gets written into the file\n    :return: None\n    \"\"\"\n    with open(filename, 'w') as f:\n        f.write(content)\n\n\ndef format_instance_name(name, platform, instances):\n    \"\"\"\n    Takes an instance name and formats it according to options specified in the instance's config.\n    :param name: the name of the instance\n    :param platform: the current molecule platform in use\n    :param instances: the current molecule instances dict in use\n    :return: formatted instance name if found in instances, otherwise None\n    \"\"\"\n    working_instance = None\n\n    # search instances for given name\n    for instance in instances:\n        if instance['name'] == name:\n            working_instance = instance\n            break\n\n    # no instance found with given name\n    if working_instance is None:\n        return\n\n    # return the default name if no options are specified for instance\n    if working_instance.get('options') is None:\n        return name\n\n    # add platform to name\n    if working_instance['options'].get('append_platform_to_hostname'):\n        return name + '-' + platform\n\n    # if we fall through, return the default name\n    return name\n\n\ndef remove_args(command_args, args, kill):\n    \"\"\"\n    Removes args so commands can be passed around easily.\n    :param command_args: list of command args from DocOpt\n    :param args: dict of arguments from DocOpt\n    :kill: list of args to remove from returned values\n    :return: pruned command_args list, pruned args dict\n    \"\"\"\n\n    new_args = {}\n    new_command_args = []\n    skip_next = False\n\n    # remove killed command args and their adjacent items\n    for item in command_args:\n        if skip_next:\n            skip_next = False\n            continue\n        if item.lower() in kill:\n            skip_next = True\n            continue\n        new_command_args.append(item)\n\n    # remove killed command args\n    for k, v in args.iteritems():\n        if k not in kill:\n            new_args[k] = v\n\n    return new_command_args, new_args\n\n\ndef debug(title, data):\n    \"\"\"\n    Prints colorized output for use when debugging portions of molecule.\n    :param title: title of debug output\n    :param data: data of debug output\n    :return: None\n    \"\"\"\n    print(''.join([colorama.Back.WHITE, colorama.Style.BRIGHT,\n                   colorama.Fore.BLACK, 'DEBUG: ' + title, colorama.Fore.RESET,\n                   colorama.Back.RESET, colorama.Style.RESET_ALL]))\n    print(''.join([colorama.Fore.BLACK, colorama.Style.BRIGHT, data,\n                   colorama.Style.RESET_ALL, colorama.Fore.RESET]))\n", "path": "molecule/utilities.py"}]}