We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
meson color output is broken with conemu (windows)
I currently use conemu with the quake-style dropdown menu, and while trying to run meson under windows, I get the following output

![screenshot 2018-04-29 00 34 23](https://user-images.githubusercontent.com/63051/39404269-0f519e72-4b45-11e8-9d15-b71667951b0f.png)

I think that on windows, it might be best to use the [colorama](https://pypi.org/project/colorama/) library as a conditional dependency on windows. This can be done inside of the `setup.py` with the `install_requires` looking like:

```python
install_requires =
  colorama;sys_platform == 'win32'
```

Alternatively, simply importing colorama causes it to "do the right thing" on non-windows platforms. This also means you can get color support for pre-Windows 10 versions (Windows 10 added VT100 escape sequence support, but it requires an explicit opt in via a win32 function call)

I'm unsure if either of these options are valid, or even wanted.
meson color output is broken with conemu (windows)
I currently use conemu with the quake-style dropdown menu, and while trying to run meson under windows, I get the following output

![screenshot 2018-04-29 00 34 23](https://user-images.githubusercontent.com/63051/39404269-0f519e72-4b45-11e8-9d15-b71667951b0f.png)

I think that on windows, it might be best to use the [colorama](https://pypi.org/project/colorama/) library as a conditional dependency on windows. This can be done inside of the `setup.py` with the `install_requires` looking like:

```python
install_requires =
  colorama;sys_platform == 'win32'
```

Alternatively, simply importing colorama causes it to "do the right thing" on non-windows platforms. This also means you can get color support for pre-Windows 10 versions (Windows 10 added VT100 escape sequence support, but it requires an explicit opt in via a win32 function call)

I'm unsure if either of these options are valid, or even wanted.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `mesonbuild/mlog.py`
Content:
```
1 # Copyright 2013-2014 The Meson development team
2 
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 
7 #     http://www.apache.org/licenses/LICENSE-2.0
8 
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14 
15 import sys, os, platform, io
16 from contextlib import contextmanager
17 
18 """This is (mostly) a standalone module used to write logging
19 information about Meson runs. Some output goes to screen,
20 some to logging dir and some goes to both."""
21 
22 if platform.system().lower() == 'windows':
23     colorize_console = os.isatty(sys.stdout.fileno()) and os.environ.get('ANSICON')
24 else:
25     colorize_console = os.isatty(sys.stdout.fileno()) and os.environ.get('TERM') != 'dumb'
26 log_dir = None
27 log_file = None
28 log_fname = 'meson-log.txt'
29 log_depth = 0
30 
31 def initialize(logdir):
32     global log_dir, log_file
33     log_dir = logdir
34     log_file = open(os.path.join(logdir, log_fname), 'w', encoding='utf8')
35 
36 def shutdown():
37     global log_file
38     if log_file is not None:
39         exception_around_goer = log_file
40         log_file = None
41         exception_around_goer.close()
42 
43 class AnsiDecorator:
44     plain_code = "\033[0m"
45 
46     def __init__(self, text, code):
47         self.text = text
48         self.code = code
49 
50     def get_text(self, with_codes):
51         if with_codes:
52             return self.code + self.text + AnsiDecorator.plain_code
53         return self.text
54 
55 def bold(text):
56     return AnsiDecorator(text, "\033[1m")
57 
58 def red(text):
59     return AnsiDecorator(text, "\033[1;31m")
60 
61 def green(text):
62     return AnsiDecorator(text, "\033[1;32m")
63 
64 def yellow(text):
65     return AnsiDecorator(text, "\033[1;33m")
66 
67 def cyan(text):
68     return AnsiDecorator(text, "\033[1;36m")
69 
70 def process_markup(args, keep):
71     arr = []
72     for arg in args:
73         if isinstance(arg, str):
74             arr.append(arg)
75         elif isinstance(arg, AnsiDecorator):
76             arr.append(arg.get_text(keep))
77         else:
78             arr.append(str(arg))
79     return arr
80 
81 def force_print(*args, **kwargs):
82     iostr = io.StringIO()
83     kwargs['file'] = iostr
84     print(*args, **kwargs)
85 
86     raw = iostr.getvalue()
87     if log_depth > 0:
88         prepend = '|' * log_depth
89         raw = prepend + raw.replace('\n', '\n' + prepend, raw.count('\n') - 1)
90 
91     # _Something_ is going to get printed.
92     try:
93         print(raw, end='')
94     except UnicodeEncodeError:
95         cleaned = raw.encode('ascii', 'replace').decode('ascii')
96         print(cleaned, end='')
97 
98 def debug(*args, **kwargs):
99     arr = process_markup(args, False)
100     if log_file is not None:
101         print(*arr, file=log_file, **kwargs) # Log file never gets ANSI codes.
102         log_file.flush()
103 
104 def log(*args, **kwargs):
105     arr = process_markup(args, False)
106     if log_file is not None:
107         print(*arr, file=log_file, **kwargs) # Log file never gets ANSI codes.
108         log_file.flush()
109     if colorize_console:
110         arr = process_markup(args, True)
111     force_print(*arr, **kwargs)
112 
113 def _log_error(severity, *args, **kwargs):
114     from . import environment
115     if severity == 'warning':
116         args = (yellow('WARNING:'),) + args
117     elif severity == 'error':
118         args = (red('ERROR:'),) + args
119     else:
120         assert False, 'Invalid severity ' + severity
121 
122     location = kwargs.pop('location', None)
123     if location is not None:
124         location_str = '{}:{}:'.format(os.path.join(location.subdir,
125                                                     environment.build_filename),
126                                        location.lineno)
127         args = (location_str,) + args
128 
129     log(*args, **kwargs)
130 
131 def error(*args, **kwargs):
132     return _log_error('error', *args, **kwargs)
133 
134 def warning(*args, **kwargs):
135     return _log_error('warning', *args, **kwargs)
136 
137 def exception(e):
138     log()
139     if hasattr(e, 'file') and hasattr(e, 'lineno') and hasattr(e, 'colno'):
140         log('%s:%d:%d:' % (e.file, e.lineno, e.colno), red('ERROR: '), e)
141     else:
142         log(red('ERROR:'), e)
143 
144 # Format a list for logging purposes as a string. It separates
145 # all but the last item with commas, and the last with 'and'.
146 def format_list(list):
147     l = len(list)
148     if l > 2:
149         return ' and '.join([', '.join(list[:-1]), list[-1]])
150     elif l == 2:
151         return ' and '.join(list)
152     elif l == 1:
153         return list[0]
154     else:
155         return ''
156 
157 @contextmanager
158 def nested():
159     global log_depth
160     log_depth += 1
161     try:
162         yield
163     finally:
164         log_depth -= 1
165
```
--- 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/mesonbuild/mlog.py b/mesonbuild/mlog.py
--- a/mesonbuild/mlog.py
+++ b/mesonbuild/mlog.py
@@ -19,8 +19,22 @@
 information about Meson runs. Some output goes to screen,
 some to logging dir and some goes to both."""
 
+def _windows_ansi():
+    from ctypes import windll, byref
+    from ctypes.wintypes import DWORD
+
+    kernel = windll.kernel32
+    stdout = kernel.GetStdHandle(-11)
+    mode = DWORD()
+    if not kernel.GetConsoleMode(stdout, byref(mode)):
+        return False
+    # ENABLE_VIRTUAL_TERMINAL_PROCESSING == 0x4
+    # If the call to enable VT processing fails (returns 0), we fallback to
+    # original behavior
+    return kernel.SetConsoleMode(stdout, mode.value | 0x4) or os.environ.get('ANSICON')
+
 if platform.system().lower() == 'windows':
-    colorize_console = os.isatty(sys.stdout.fileno()) and os.environ.get('ANSICON')
+    colorize_console = os.isatty(sys.stdout.fileno()) and _windows_ansi()
 else:
     colorize_console = os.isatty(sys.stdout.fileno()) and os.environ.get('TERM') != 'dumb'
 log_dir = None

{"golden_diff": "diff --git a/mesonbuild/mlog.py b/mesonbuild/mlog.py\n--- a/mesonbuild/mlog.py\n+++ b/mesonbuild/mlog.py\n@@ -19,8 +19,22 @@\n information about Meson runs. Some output goes to screen,\n some to logging dir and some goes to both.\"\"\"\n \n+def _windows_ansi():\n+    from ctypes import windll, byref\n+    from ctypes.wintypes import DWORD\n+\n+    kernel = windll.kernel32\n+    stdout = kernel.GetStdHandle(-11)\n+    mode = DWORD()\n+    if not kernel.GetConsoleMode(stdout, byref(mode)):\n+        return False\n+    # ENABLE_VIRTUAL_TERMINAL_PROCESSING == 0x4\n+    # If the call to enable VT processing fails (returns 0), we fallback to\n+    # original behavior\n+    return kernel.SetConsoleMode(stdout, mode.value | 0x4) or os.environ.get('ANSICON')\n+\n if platform.system().lower() == 'windows':\n-    colorize_console = os.isatty(sys.stdout.fileno()) and os.environ.get('ANSICON')\n+    colorize_console = os.isatty(sys.stdout.fileno()) and _windows_ansi()\n else:\n     colorize_console = os.isatty(sys.stdout.fileno()) and os.environ.get('TERM') != 'dumb'\n log_dir = None\n", "issue": "meson color output is broken with conemu (windows)\nI currently use conemu with the quake-style dropdown menu, and while trying to run meson under windows, I get the following output\r\n\r\n![screenshot 2018-04-29 00 34 23](https://user-images.githubusercontent.com/63051/39404269-0f519e72-4b45-11e8-9d15-b71667951b0f.png)\r\n\r\nI think that on windows, it might be best to use the [colorama](https://pypi.org/project/colorama/) library as a conditional dependency on windows. This can be done inside of the `setup.py` with the `install_requires` looking like:\r\n\r\n```python\r\ninstall_requires =\r\n  colorama;sys_platform == 'win32'\r\n```\r\n\r\nAlternatively, simply importing colorama causes it to \"do the right thing\" on non-windows platforms. This also means you can get color support for pre-Windows 10 versions (Windows 10 added VT100 escape sequence support, but it requires an explicit opt in via a win32 function call)\r\n\r\nI'm unsure if either of these options are valid, or even wanted.\nmeson color output is broken with conemu (windows)\nI currently use conemu with the quake-style dropdown menu, and while trying to run meson under windows, I get the following output\r\n\r\n![screenshot 2018-04-29 00 34 23](https://user-images.githubusercontent.com/63051/39404269-0f519e72-4b45-11e8-9d15-b71667951b0f.png)\r\n\r\nI think that on windows, it might be best to use the [colorama](https://pypi.org/project/colorama/) library as a conditional dependency on windows. This can be done inside of the `setup.py` with the `install_requires` looking like:\r\n\r\n```python\r\ninstall_requires =\r\n  colorama;sys_platform == 'win32'\r\n```\r\n\r\nAlternatively, simply importing colorama causes it to \"do the right thing\" on non-windows platforms. This also means you can get color support for pre-Windows 10 versions (Windows 10 added VT100 escape sequence support, but it requires an explicit opt in via a win32 function call)\r\n\r\nI'm unsure if either of these options are valid, or even wanted.\n", "before_files": [{"content": "# Copyright 2013-2014 The Meson development team\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n\n#     http://www.apache.org/licenses/LICENSE-2.0\n\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nimport sys, os, platform, io\nfrom contextlib import contextmanager\n\n\"\"\"This is (mostly) a standalone module used to write logging\ninformation about Meson runs. Some output goes to screen,\nsome to logging dir and some goes to both.\"\"\"\n\nif platform.system().lower() == 'windows':\n    colorize_console = os.isatty(sys.stdout.fileno()) and os.environ.get('ANSICON')\nelse:\n    colorize_console = os.isatty(sys.stdout.fileno()) and os.environ.get('TERM') != 'dumb'\nlog_dir = None\nlog_file = None\nlog_fname = 'meson-log.txt'\nlog_depth = 0\n\ndef initialize(logdir):\n    global log_dir, log_file\n    log_dir = logdir\n    log_file = open(os.path.join(logdir, log_fname), 'w', encoding='utf8')\n\ndef shutdown():\n    global log_file\n    if log_file is not None:\n        exception_around_goer = log_file\n        log_file = None\n        exception_around_goer.close()\n\nclass AnsiDecorator:\n    plain_code = \"\\033[0m\"\n\n    def __init__(self, text, code):\n        self.text = text\n        self.code = code\n\n    def get_text(self, with_codes):\n        if with_codes:\n            return self.code + self.text + AnsiDecorator.plain_code\n        return self.text\n\ndef bold(text):\n    return AnsiDecorator(text, \"\\033[1m\")\n\ndef red(text):\n    return AnsiDecorator(text, \"\\033[1;31m\")\n\ndef green(text):\n    return AnsiDecorator(text, \"\\033[1;32m\")\n\ndef yellow(text):\n    return AnsiDecorator(text, \"\\033[1;33m\")\n\ndef cyan(text):\n    return AnsiDecorator(text, \"\\033[1;36m\")\n\ndef process_markup(args, keep):\n    arr = []\n    for arg in args:\n        if isinstance(arg, str):\n            arr.append(arg)\n        elif isinstance(arg, AnsiDecorator):\n            arr.append(arg.get_text(keep))\n        else:\n            arr.append(str(arg))\n    return arr\n\ndef force_print(*args, **kwargs):\n    iostr = io.StringIO()\n    kwargs['file'] = iostr\n    print(*args, **kwargs)\n\n    raw = iostr.getvalue()\n    if log_depth > 0:\n        prepend = '|' * log_depth\n        raw = prepend + raw.replace('\\n', '\\n' + prepend, raw.count('\\n') - 1)\n\n    # _Something_ is going to get printed.\n    try:\n        print(raw, end='')\n    except UnicodeEncodeError:\n        cleaned = raw.encode('ascii', 'replace').decode('ascii')\n        print(cleaned, end='')\n\ndef debug(*args, **kwargs):\n    arr = process_markup(args, False)\n    if log_file is not None:\n        print(*arr, file=log_file, **kwargs) # Log file never gets ANSI codes.\n        log_file.flush()\n\ndef log(*args, **kwargs):\n    arr = process_markup(args, False)\n    if log_file is not None:\n        print(*arr, file=log_file, **kwargs) # Log file never gets ANSI codes.\n        log_file.flush()\n    if colorize_console:\n        arr = process_markup(args, True)\n    force_print(*arr, **kwargs)\n\ndef _log_error(severity, *args, **kwargs):\n    from . import environment\n    if severity == 'warning':\n        args = (yellow('WARNING:'),) + args\n    elif severity == 'error':\n        args = (red('ERROR:'),) + args\n    else:\n        assert False, 'Invalid severity ' + severity\n\n    location = kwargs.pop('location', None)\n    if location is not None:\n        location_str = '{}:{}:'.format(os.path.join(location.subdir,\n                                                    environment.build_filename),\n                                       location.lineno)\n        args = (location_str,) + args\n\n    log(*args, **kwargs)\n\ndef error(*args, **kwargs):\n    return _log_error('error', *args, **kwargs)\n\ndef warning(*args, **kwargs):\n    return _log_error('warning', *args, **kwargs)\n\ndef exception(e):\n    log()\n    if hasattr(e, 'file') and hasattr(e, 'lineno') and hasattr(e, 'colno'):\n        log('%s:%d:%d:' % (e.file, e.lineno, e.colno), red('ERROR: '), e)\n    else:\n        log(red('ERROR:'), e)\n\n# Format a list for logging purposes as a string. It separates\n# all but the last item with commas, and the last with 'and'.\ndef format_list(list):\n    l = len(list)\n    if l > 2:\n        return ' and '.join([', '.join(list[:-1]), list[-1]])\n    elif l == 2:\n        return ' and '.join(list)\n    elif l == 1:\n        return list[0]\n    else:\n        return ''\n\n@contextmanager\ndef nested():\n    global log_depth\n    log_depth += 1\n    try:\n        yield\n    finally:\n        log_depth -= 1\n", "path": "mesonbuild/mlog.py"}], "after_files": [{"content": "# Copyright 2013-2014 The Meson development team\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n\n#     http://www.apache.org/licenses/LICENSE-2.0\n\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nimport sys, os, platform, io\nfrom contextlib import contextmanager\n\n\"\"\"This is (mostly) a standalone module used to write logging\ninformation about Meson runs. Some output goes to screen,\nsome to logging dir and some goes to both.\"\"\"\n\ndef _windows_ansi():\n    from ctypes import windll, byref\n    from ctypes.wintypes import DWORD\n\n    kernel = windll.kernel32\n    stdout = kernel.GetStdHandle(-11)\n    mode = DWORD()\n    if not kernel.GetConsoleMode(stdout, byref(mode)):\n        return False\n    # ENABLE_VIRTUAL_TERMINAL_PROCESSING == 0x4\n    # If the call to enable VT processing fails (returns 0), we fallback to\n    # original behavior\n    return kernel.SetConsoleMode(stdout, mode.value | 0x4) or os.environ.get('ANSICON')\n\nif platform.system().lower() == 'windows':\n    colorize_console = os.isatty(sys.stdout.fileno()) and _windows_ansi()\nelse:\n    colorize_console = os.isatty(sys.stdout.fileno()) and os.environ.get('TERM') != 'dumb'\nlog_dir = None\nlog_file = None\nlog_fname = 'meson-log.txt'\nlog_depth = 0\n\ndef initialize(logdir):\n    global log_dir, log_file\n    log_dir = logdir\n    log_file = open(os.path.join(logdir, log_fname), 'w', encoding='utf8')\n\ndef shutdown():\n    global log_file\n    if log_file is not None:\n        exception_around_goer = log_file\n        log_file = None\n        exception_around_goer.close()\n\nclass AnsiDecorator:\n    plain_code = \"\\033[0m\"\n\n    def __init__(self, text, code):\n        self.text = text\n        self.code = code\n\n    def get_text(self, with_codes):\n        if with_codes:\n            return self.code + self.text + AnsiDecorator.plain_code\n        return self.text\n\ndef bold(text):\n    return AnsiDecorator(text, \"\\033[1m\")\n\ndef red(text):\n    return AnsiDecorator(text, \"\\033[1;31m\")\n\ndef green(text):\n    return AnsiDecorator(text, \"\\033[1;32m\")\n\ndef yellow(text):\n    return AnsiDecorator(text, \"\\033[1;33m\")\n\ndef cyan(text):\n    return AnsiDecorator(text, \"\\033[1;36m\")\n\ndef process_markup(args, keep):\n    arr = []\n    for arg in args:\n        if isinstance(arg, str):\n            arr.append(arg)\n        elif isinstance(arg, AnsiDecorator):\n            arr.append(arg.get_text(keep))\n        else:\n            arr.append(str(arg))\n    return arr\n\ndef force_print(*args, **kwargs):\n    iostr = io.StringIO()\n    kwargs['file'] = iostr\n    print(*args, **kwargs)\n\n    raw = iostr.getvalue()\n    if log_depth > 0:\n        prepend = '|' * log_depth\n        raw = prepend + raw.replace('\\n', '\\n' + prepend, raw.count('\\n') - 1)\n\n    # _Something_ is going to get printed.\n    try:\n        print(raw, end='')\n    except UnicodeEncodeError:\n        cleaned = raw.encode('ascii', 'replace').decode('ascii')\n        print(cleaned, end='')\n\ndef debug(*args, **kwargs):\n    arr = process_markup(args, False)\n    if log_file is not None:\n        print(*arr, file=log_file, **kwargs) # Log file never gets ANSI codes.\n        log_file.flush()\n\ndef log(*args, **kwargs):\n    arr = process_markup(args, False)\n    if log_file is not None:\n        print(*arr, file=log_file, **kwargs) # Log file never gets ANSI codes.\n        log_file.flush()\n    if colorize_console:\n        arr = process_markup(args, True)\n    force_print(*arr, **kwargs)\n\ndef _log_error(severity, *args, **kwargs):\n    from . import environment\n    if severity == 'warning':\n        args = (yellow('WARNING:'),) + args\n    elif severity == 'error':\n        args = (red('ERROR:'),) + args\n    else:\n        assert False, 'Invalid severity ' + severity\n\n    location = kwargs.pop('location', None)\n    if location is not None:\n        location_str = '{}:{}:'.format(os.path.join(location.subdir,\n                                                    environment.build_filename),\n                                       location.lineno)\n        args = (location_str,) + args\n\n    log(*args, **kwargs)\n\ndef error(*args, **kwargs):\n    return _log_error('error', *args, **kwargs)\n\ndef warning(*args, **kwargs):\n    return _log_error('warning', *args, **kwargs)\n\ndef exception(e):\n    log()\n    if hasattr(e, 'file') and hasattr(e, 'lineno') and hasattr(e, 'colno'):\n        log('%s:%d:%d:' % (e.file, e.lineno, e.colno), red('ERROR: '), e)\n    else:\n        log(red('ERROR:'), e)\n\n# Format a list for logging purposes as a string. It separates\n# all but the last item with commas, and the last with 'and'.\ndef format_list(list):\n    l = len(list)\n    if l > 2:\n        return ' and '.join([', '.join(list[:-1]), list[-1]])\n    elif l == 2:\n        return ' and '.join(list)\n    elif l == 1:\n        return list[0]\n    else:\n        return ''\n\n@contextmanager\ndef nested():\n    global log_depth\n    log_depth += 1\n    try:\n        yield\n    finally:\n        log_depth -= 1\n", "path": "mesonbuild/mlog.py"}]}