Update colorama to 0.4.1

Fixes colorama unintentionally overriding multiple sys.stdout wrappers of our own.
And provides a fix for a SyntaxWarning on Python 3.8:
C:\Google\depot_tools\third_party\colorama\ansitowin32.py:43: SyntaxWarning: invalid escape sequence \[
  ANSI_RE = re.compile('\033\[((?:\d|;)*)([a-zA-Z])')

Tests are updated to account for the annotation wrapper no longer being overriden.
A fix by agable for the annotation wrapper working with carriage returns is also included (https://chromium-review.googlesource.com/c/chromium/tools/depot_tools/+/1592612).

Bug: 958138, 958321
Change-Id: I2fe1def85c66cfe5229a1c25c2f677e498593eea
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/tools/depot_tools/+/1591513
Reviewed-by: Aaron Gable <agable@chromium.org>
Reviewed-by: Marc-Antoine Ruel <maruel@chromium.org>
Commit-Queue: Raul Tambre <raul@tambre.ee>
Auto-Submit: Raul Tambre <raul@tambre.ee>
diff --git a/gclient_utils.py b/gclient_utils.py
index 5b751b4..ead81c7 100644
--- a/gclient_utils.py
+++ b/gclient_utils.py
@@ -433,10 +433,20 @@
 
     # Continue lockless.
     obj[0] += out
-    while '\n' in obj[0]:
-      line, remaining = obj[0].split('\n', 1)
-      if line:
-        self._wrapped.write('%d>%s\n' % (index, line))
+    while True:
+      # TODO(agable): find both of these with a single pass.
+      cr_loc = obj[0].find('\r')
+      lf_loc = obj[0].find('\n')
+      if cr_loc == lf_loc == -1:
+        break
+      elif cr_loc == -1 or (lf_loc >= 0 and lf_loc < cr_loc):
+        line, remaining = obj[0].split('\n', 1)
+        if line:
+          self._wrapped.write('%d>%s\n' % (index, line))
+      elif lf_loc == -1 or (cr_loc >= 0 and cr_loc < lf_loc):
+        line, remaining = obj[0].split('\r', 1)
+        if line:
+          self._wrapped.write('%d>%s\r' % (index, line))
       obj[0] = remaining
 
   def flush(self):
diff --git a/tests/gclient_smoketest.py b/tests/gclient_smoketest.py
index 94dce2e..c8b9b50 100755
--- a/tests/gclient_smoketest.py
+++ b/tests/gclient_smoketest.py
@@ -58,15 +58,23 @@
             process.returncode)
 
   def untangle(self, stdout):
+    """Separates output based on thread IDs."""
     tasks = {}
     remaining = []
+    task_id = 0
     for line in stdout.splitlines(False):
       m = re.match(r'^(\d)+>(.*)$', line)
       if not m:
-        remaining.append(line)
+        if task_id:
+          # Lines broken with carriage breaks don't have a thread ID, but belong
+          # to the last seen thread ID.
+          tasks.setdefault(task_id, []).append(line)
+        else:
+          remaining.append(line)
       else:
         self.assertEquals([], remaining)
-        tasks.setdefault(int(m.group(1)), []).append(m.group(2))
+        task_id = int(m.group(1))
+        tasks.setdefault(task_id, []).append(m.group(2))
     out = []
     for key in sorted(tasks.iterkeys()):
       out.extend(tasks[key])
diff --git a/third_party/colorama/LICENSE.txt b/third_party/colorama/LICENSE.txt
index 5f56779..3105888 100644
--- a/third_party/colorama/LICENSE.txt
+++ b/third_party/colorama/LICENSE.txt
@@ -25,4 +25,3 @@
 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
diff --git a/third_party/colorama/README.chromium b/third_party/colorama/README.chromium
index 2605ac9..9f7d6e9 100644
--- a/third_party/colorama/README.chromium
+++ b/third_party/colorama/README.chromium
@@ -1,7 +1,7 @@
 Name: colorama
-URL: http://code.google.com/p/colorama
-Version: 5a3100113a3a (0.2.7)
-Revision: 5a3100113a3a
+URL: https://github.com/tartley/colorama
+Version: b71bec90d4770d4124ad95d70cc6a4c9289bbadf (0.4.1)
+Revision: b71bec90d4770d4124ad95d70cc6a4c9289bbadf
 
 Description:
 Provides a simple cross-platform API to print colored terminal text from Python
@@ -9,5 +9,4 @@
 
 Additional changes:
 - Kept colorama/ but removed colorama/tests/.
-- Copied LICENSE.txt and README.txt.
-- Converted all the files to LF EOL style.
+- Copied LICENSE.txt and README.rst.
diff --git a/third_party/colorama/README.rst b/third_party/colorama/README.rst
new file mode 100644
index 0000000..fb6fb3d
--- /dev/null
+++ b/third_party/colorama/README.rst
@@ -0,0 +1,346 @@
+.. image:: https://img.shields.io/pypi/v/colorama.svg
+    :target: https://pypi.org/project/colorama/
+    :alt: Latest Version
+
+.. image:: https://img.shields.io/pypi/pyversions/colorama.svg
+    :target: https://pypi.org/project/colorama/
+    :alt: Supported Python versions
+
+.. image:: https://travis-ci.org/tartley/colorama.svg?branch=master
+    :target: https://travis-ci.org/tartley/colorama
+    :alt: Build Status
+
+Download and docs:
+    https://pypi.org/project/colorama/
+Source code & Development:
+    https://github.com/tartley/colorama
+
+Description
+===========
+
+Makes ANSI escape character sequences (for producing colored terminal text and
+cursor positioning) work under MS Windows.
+
+ANSI escape character sequences have long been used to produce colored terminal
+text and cursor positioning on Unix and Macs. Colorama makes this work on
+Windows, too, by wrapping ``stdout``, stripping ANSI sequences it finds (which
+would appear as gobbledygook in the output), and converting them into the
+appropriate win32 calls to modify the state of the terminal. On other platforms,
+Colorama does nothing.
+
+Colorama also provides some shortcuts to help generate ANSI sequences
+but works fine in conjunction with any other ANSI sequence generation library,
+such as the venerable Termcolor (https://pypi.org/project/termcolor/)
+or the fabulous Blessings (https://pypi.org/project/blessings/).
+
+This has the upshot of providing a simple cross-platform API for printing
+colored terminal text from Python, and has the happy side-effect that existing
+applications or libraries which use ANSI sequences to produce colored output on
+Linux or Macs can now also work on Windows, simply by calling
+``colorama.init()``.
+
+An alternative approach is to install ``ansi.sys`` on Windows machines, which
+provides the same behaviour for all applications running in terminals. Colorama
+is intended for situations where that isn't easy (e.g., maybe your app doesn't
+have an installer.)
+
+Demo scripts in the source code repository print some colored text using
+ANSI sequences. Compare their output under Gnome-terminal's built in ANSI
+handling, versus on Windows Command-Prompt using Colorama:
+
+.. image:: https://github.com/tartley/colorama/raw/master/screenshots/ubuntu-demo.png
+    :width: 661
+    :height: 357
+    :alt: ANSI sequences on Ubuntu under gnome-terminal.
+
+.. image:: https://github.com/tartley/colorama/raw/master/screenshots/windows-demo.png
+    :width: 668
+    :height: 325
+    :alt: Same ANSI sequences on Windows, using Colorama.
+
+These screengrabs show that, on Windows, Colorama does not support ANSI 'dim
+text'; it looks the same as 'normal text'.
+
+
+License
+=======
+
+Copyright Jonathan Hartley 2013. BSD 3-Clause license; see LICENSE file.
+
+
+Dependencies
+============
+
+None, other than Python. Tested on Python 2.7, 3.4, 3.5 and 3.6.
+
+Usage
+=====
+
+Initialisation
+--------------
+
+Applications should initialise Colorama using:
+
+.. code-block:: python
+
+    from colorama import init
+    init()
+
+On Windows, calling ``init()`` will filter ANSI escape sequences out of any
+text sent to ``stdout`` or ``stderr``, and replace them with equivalent Win32
+calls.
+
+On other platforms, calling ``init()`` has no effect (unless you request other
+optional functionality; see "Init Keyword Args", below). By design, this permits
+applications to call ``init()`` unconditionally on all platforms, after which
+ANSI output should just work.
+
+To stop using colorama before your program exits, simply call ``deinit()``.
+This will restore ``stdout`` and ``stderr`` to their original values, so that
+Colorama is disabled. To resume using Colorama again, call ``reinit()``; it is
+cheaper to calling ``init()`` again (but does the same thing).
+
+
+Colored Output
+--------------
+
+Cross-platform printing of colored text can then be done using Colorama's
+constant shorthand for ANSI escape sequences:
+
+.. code-block:: python
+
+    from colorama import Fore, Back, Style
+    print(Fore.RED + 'some red text')
+    print(Back.GREEN + 'and with a green background')
+    print(Style.DIM + 'and in dim text')
+    print(Style.RESET_ALL)
+    print('back to normal now')
+
+...or simply by manually printing ANSI sequences from your own code:
+
+.. code-block:: python
+
+    print('\033[31m' + 'some red text')
+    print('\033[39m') # and reset to default color
+
+...or, Colorama can be used happily in conjunction with existing ANSI libraries
+such as Termcolor:
+
+.. code-block:: python
+
+    from colorama import init
+    from termcolor import colored
+
+    # use Colorama to make Termcolor work on Windows too
+    init()
+
+    # then use Termcolor for all colored text output
+    print(colored('Hello, World!', 'green', 'on_red'))
+
+Available formatting constants are::
+
+    Fore: BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE, RESET.
+    Back: BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE, RESET.
+    Style: DIM, NORMAL, BRIGHT, RESET_ALL
+
+``Style.RESET_ALL`` resets foreground, background, and brightness. Colorama will
+perform this reset automatically on program exit.
+
+
+Cursor Positioning
+------------------
+
+ANSI codes to reposition the cursor are supported. See ``demos/demo06.py`` for
+an example of how to generate them.
+
+
+Init Keyword Args
+-----------------
+
+``init()`` accepts some ``**kwargs`` to override default behaviour.
+
+init(autoreset=False):
+    If you find yourself repeatedly sending reset sequences to turn off color
+    changes at the end of every print, then ``init(autoreset=True)`` will
+    automate that:
+
+    .. code-block:: python
+
+        from colorama import init
+        init(autoreset=True)
+        print(Fore.RED + 'some red text')
+        print('automatically back to default color again')
+
+init(strip=None):
+    Pass ``True`` or ``False`` to override whether ansi codes should be
+    stripped from the output. The default behaviour is to strip if on Windows
+    or if output is redirected (not a tty).
+
+init(convert=None):
+    Pass ``True`` or ``False`` to override whether to convert ANSI codes in the
+    output into win32 calls. The default behaviour is to convert if on Windows
+    and output is to a tty (terminal).
+
+init(wrap=True):
+    On Windows, colorama works by replacing ``sys.stdout`` and ``sys.stderr``
+    with proxy objects, which override the ``.write()`` method to do their work.
+    If this wrapping causes you problems, then this can be disabled by passing
+    ``init(wrap=False)``. The default behaviour is to wrap if ``autoreset`` or
+    ``strip`` or ``convert`` are True.
+
+    When wrapping is disabled, colored printing on non-Windows platforms will
+    continue to work as normal. To do cross-platform colored output, you can
+    use Colorama's ``AnsiToWin32`` proxy directly:
+
+    .. code-block:: python
+
+        import sys
+        from colorama import init, AnsiToWin32
+        init(wrap=False)
+        stream = AnsiToWin32(sys.stderr).stream
+
+        # Python 2
+        print >>stream, Fore.BLUE + 'blue text on stderr'
+
+        # Python 3
+        print(Fore.BLUE + 'blue text on stderr', file=stream)
+
+
+Status & Known Problems
+=======================
+
+I've personally only tested it on Windows XP (CMD, Console2), Ubuntu
+(gnome-terminal, xterm), and OS X.
+
+Some presumably valid ANSI sequences aren't recognised (see details below),
+but to my knowledge nobody has yet complained about this. Puzzling.
+
+See outstanding issues and wishlist:
+https://github.com/tartley/colorama/issues
+
+If anything doesn't work for you, or doesn't do what you expected or hoped for,
+I'd love to hear about it on that issues list, would be delighted by patches,
+and would be happy to grant commit access to anyone who submits a working patch
+or two.
+
+
+Recognised ANSI Sequences
+=========================
+
+ANSI sequences generally take the form:
+
+    ESC [ <param> ; <param> ... <command>
+
+Where ``<param>`` is an integer, and ``<command>`` is a single letter. Zero or
+more params are passed to a ``<command>``. If no params are passed, it is
+generally synonymous with passing a single zero. No spaces exist in the
+sequence; they have been inserted here simply to read more easily.
+
+The only ANSI sequences that colorama converts into win32 calls are::
+
+    ESC [ 0 m       # reset all (colors and brightness)
+    ESC [ 1 m       # bright
+    ESC [ 2 m       # dim (looks same as normal brightness)
+    ESC [ 22 m      # normal brightness
+
+    # FOREGROUND:
+    ESC [ 30 m      # black
+    ESC [ 31 m      # red
+    ESC [ 32 m      # green
+    ESC [ 33 m      # yellow
+    ESC [ 34 m      # blue
+    ESC [ 35 m      # magenta
+    ESC [ 36 m      # cyan
+    ESC [ 37 m      # white
+    ESC [ 39 m      # reset
+
+    # BACKGROUND
+    ESC [ 40 m      # black
+    ESC [ 41 m      # red
+    ESC [ 42 m      # green
+    ESC [ 43 m      # yellow
+    ESC [ 44 m      # blue
+    ESC [ 45 m      # magenta
+    ESC [ 46 m      # cyan
+    ESC [ 47 m      # white
+    ESC [ 49 m      # reset
+
+    # cursor positioning
+    ESC [ y;x H     # position cursor at x across, y down
+    ESC [ y;x f     # position cursor at x across, y down
+    ESC [ n A       # move cursor n lines up
+    ESC [ n B       # move cursor n lines down
+    ESC [ n C       # move cursor n characters forward
+    ESC [ n D       # move cursor n characters backward
+
+    # clear the screen
+    ESC [ mode J    # clear the screen
+
+    # clear the line
+    ESC [ mode K    # clear the line
+
+Multiple numeric params to the ``'m'`` command can be combined into a single
+sequence::
+
+    ESC [ 36 ; 45 ; 1 m     # bright cyan text on magenta background
+
+All other ANSI sequences of the form ``ESC [ <param> ; <param> ... <command>``
+are silently stripped from the output on Windows.
+
+Any other form of ANSI sequence, such as single-character codes or alternative
+initial characters, are not recognised or stripped. It would be cool to add
+them though. Let me know if it would be useful for you, via the Issues on
+GitHub.
+
+
+Development
+===========
+
+Help and fixes welcome!
+
+Running tests requires:
+
+- Michael Foord's ``mock`` module to be installed.
+- Tests are written using 2010-era updates to ``unittest``
+
+To run tests::
+
+   python -m unittest discover -p *_test.py
+
+This, like a few other handy commands, is captured in a ``Makefile``.
+
+If you use nose to run the tests, you must pass the ``-s`` flag; otherwise,
+``nosetests`` applies its own proxy to ``stdout``, which confuses the unit
+tests.
+
+
+Thanks
+======
+* Marc Schlaich (schlamar) for a ``setup.py`` fix for Python2.5.
+* Marc Abramowitz, reported & fixed a crash on exit with closed ``stdout``,
+  providing a solution to issue #7's setuptools/distutils debate,
+  and other fixes.
+* User 'eryksun', for guidance on correctly instantiating ``ctypes.windll``.
+* Matthew McCormick for politely pointing out a longstanding crash on non-Win.
+* Ben Hoyt, for a magnificent fix under 64-bit Windows.
+* Jesse at Empty Square for submitting a fix for examples in the README.
+* User 'jamessp', an observant documentation fix for cursor positioning.
+* User 'vaal1239', Dave Mckee & Lackner Kristof for a tiny but much-needed Win7
+  fix.
+* Julien Stuyck, for wisely suggesting Python3 compatible updates to README.
+* Daniel Griffith for multiple fabulous patches.
+* Oscar Lesta for a valuable fix to stop ANSI chars being sent to non-tty
+  output.
+* Roger Binns, for many suggestions, valuable feedback, & bug reports.
+* Tim Golden for thought and much appreciated feedback on the initial idea.
+* User 'Zearin' for updates to the README file.
+* John Szakmeister for adding support for light colors
+* Charles Merriam for adding documentation to demos
+* Jurko for a fix on 64-bit Windows CPython2.5 w/o ctypes
+* Florian Bruhin for a fix when stdout or stderr are None
+* Thomas Weininger for fixing ValueError on Windows
+* Remi Rampin for better Github integration and fixes to the README file
+* Simeon Visser for closing a file handle using 'with' and updating classifiers
+  to include Python 3.3 and 3.4
+* Andy Neff for fixing RESET of LIGHT_EX colors.
+* Jonathan Hartley for the initial idea and implementation.
diff --git a/third_party/colorama/README.txt b/third_party/colorama/README.txt
deleted file mode 100644
index 8910ba5..0000000
--- a/third_party/colorama/README.txt
+++ /dev/null
@@ -1,304 +0,0 @@
-Download and docs:
-    http://pypi.python.org/pypi/colorama
-Development:
-    http://code.google.com/p/colorama
-Discussion group:
-     https://groups.google.com/forum/#!forum/python-colorama
-
-Description
-===========
-
-Makes ANSI escape character sequences for producing colored terminal text and
-cursor positioning work under MS Windows.
-
-ANSI escape character sequences have long been used to produce colored terminal
-text and cursor positioning on Unix and Macs. Colorama makes this work on
-Windows, too, by wrapping stdout, stripping ANSI sequences it finds (which
-otherwise show up as gobbledygook in your output), and converting them into the
-appropriate win32 calls to modify the state of the terminal. On other platforms,
-Colorama does nothing.
-
-Colorama also provides some shortcuts to help generate ANSI sequences
-but works fine in conjunction with any other ANSI sequence generation library,
-such as Termcolor (http://pypi.python.org/pypi/termcolor.)
-
-This has the upshot of providing a simple cross-platform API for printing
-colored terminal text from Python, and has the happy side-effect that existing
-applications or libraries which use ANSI sequences to produce colored output on
-Linux or Macs can now also work on Windows, simply by calling
-``colorama.init()``.
-
-An alternative approach is to install 'ansi.sys' on Windows machines, which
-provides the same behaviour for all applications running in terminals. Colorama
-is intended for situations where that isn't easy (e.g. maybe your app doesn't
-have an installer.)
-
-Demo scripts in the source code repository prints some colored text using
-ANSI sequences. Compare their output under Gnome-terminal's built in ANSI
-handling, versus on Windows Command-Prompt using Colorama:
-
-.. image:: http://colorama.googlecode.com/hg/screenshots/ubuntu-demo.png
-    :width: 661
-    :height: 357
-    :alt: ANSI sequences on Ubuntu under gnome-terminal.
-
-.. image:: http://colorama.googlecode.com/hg/screenshots/windows-demo.png
-    :width: 668
-    :height: 325
-    :alt: Same ANSI sequences on Windows, using Colorama.
-
-These screengrabs show that Colorama on Windows does not support ANSI 'dim
-text': it looks the same as 'normal text'.
-
-
-License
-=======
-
-Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file.
-
-
-Dependencies
-============
-
-None, other than Python. Tested on Python 2.5.5, 2.6.5, 2.7, 3.1.2, and 3.2
-
-Usage
-=====
-
-Initialisation
---------------
-
-Applications should initialise Colorama using::
-
-    from colorama import init
-    init()
-
-If you are on Windows, the call to ``init()`` will start filtering ANSI escape
-sequences out of any text sent to stdout or stderr, and will replace them with
-equivalent Win32 calls.
-
-Calling ``init()`` has no effect on other platforms (unless you request other
-optional functionality, see keyword args below.) The intention is that
-applications can call ``init()`` unconditionally on all platforms, after which
-ANSI output should just work.
-
-To stop using colorama before your program exits, simply call ``deinit()``.
-This will restore stdout and stderr to their original values, so that Colorama
-is disabled. To start using Colorama again, call ``reinit()``, which wraps
-stdout and stderr again, but is cheaper to call than doing ``init()`` all over
-again.
-
-
-Colored Output
---------------
-
-Cross-platform printing of colored text can then be done using Colorama's
-constant shorthand for ANSI escape sequences::
-
-    from colorama import Fore, Back, Style
-    print(Fore.RED + 'some red text')
-    print(Back.GREEN + 'and with a green background')
-    print(Style.DIM + 'and in dim text')
-    print(Fore.RESET + Back.RESET + Style.RESET_ALL)
-    print('back to normal now')
-
-or simply by manually printing ANSI sequences from your own code::
-
-    print('/033[31m' + 'some red text')
-    print('/033[30m' # and reset to default color)
-
-or Colorama can be used happily in conjunction with existing ANSI libraries
-such as Termcolor::
-
-    from colorama import init
-    from termcolor import colored
-
-    # use Colorama to make Termcolor work on Windows too
-    init()
-
-    # then use Termcolor for all colored text output
-    print(colored('Hello, World!', 'green', 'on_red'))
-
-Available formatting constants are::
-
-    Fore: BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE, RESET.
-    Back: BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE, RESET.
-    Style: DIM, NORMAL, BRIGHT, RESET_ALL
-
-Style.RESET_ALL resets foreground, background and brightness. Colorama will
-perform this reset automatically on program exit.
-
-
-Cursor Positioning
-------------------
-
-ANSI codes to reposition the cursor are supported. See demos/demo06.py for
-an example of how to generate them.
-
-
-Init Keyword Args
------------------
-
-``init()`` accepts some kwargs to override default behaviour.
-
-init(autoreset=False):
-    If you find yourself repeatedly sending reset sequences to turn off color
-    changes at the end of every print, then ``init(autoreset=True)`` will
-    automate that::
-
-        from colorama import init
-        init(autoreset=True)
-        print(Fore.RED + 'some red text')
-        print('automatically back to default color again')
-
-init(strip=None):
-    Pass ``True`` or ``False`` to override whether ansi codes should be
-    stripped from the output. The default behaviour is to strip if on Windows.
-
-init(convert=None):
-    Pass ``True`` or ``False`` to override whether to convert ansi codes in the
-    output into win32 calls. The default behaviour is to convert if on Windows
-    and output is to a tty (terminal).
-
-init(wrap=True):
-    On Windows, colorama works by replacing ``sys.stdout`` and ``sys.stderr``
-    with proxy objects, which override the .write() method to do their work. If
-    this wrapping causes you problems, then this can be disabled by passing
-    ``init(wrap=False)``. The default behaviour is to wrap if autoreset or
-    strip or convert are True.
-
-    When wrapping is disabled, colored printing on non-Windows platforms will
-    continue to work as normal. To do cross-platform colored output, you can
-    use Colorama's ``AnsiToWin32`` proxy directly::
-
-        import sys
-        from colorama import init, AnsiToWin32
-        init(wrap=False)
-        stream = AnsiToWin32(sys.stderr).stream
-
-        # Python 2
-        print >>stream, Fore.BLUE + 'blue text on stderr'
-
-        # Python 3
-        print(Fore.BLUE + 'blue text on stderr', file=stream)
-
-
-Status & Known Problems
-=======================
-
-I've personally only tested it on WinXP (CMD, Console2), Ubuntu
-(gnome-terminal, xterm), and OSX.
-
-Some presumably valid ANSI sequences aren't recognised (see details below)
-but to my knowledge nobody has yet complained about this. Puzzling.
-
-See outstanding issues and wishlist at:
-http://code.google.com/p/colorama/issues/list
-
-If anything doesn't work for you, or doesn't do what you expected or hoped for,
-I'd love to hear about it on that issues list, would be delighted by patches,
-and would be happy to grant commit access to anyone who submits a working patch
-or two.
-
-
-Recognised ANSI Sequences
-=========================
-
-ANSI sequences generally take the form:
-
-    ESC [ <param> ; <param> ... <command>
-
-Where <param> is an integer, and <command> is a single letter. Zero or more
-params are passed to a <command>. If no params are passed, it is generally
-synonymous with passing a single zero. No spaces exist in the sequence, they
-have just been inserted here to make it easy to read.
-
-The only ANSI sequences that colorama converts into win32 calls are::
-
-    ESC [ 0 m       # reset all (colors and brightness)
-    ESC [ 1 m       # bright
-    ESC [ 2 m       # dim (looks same as normal brightness)
-    ESC [ 22 m      # normal brightness
-
-    # FOREGROUND:
-    ESC [ 30 m      # black
-    ESC [ 31 m      # red
-    ESC [ 32 m      # green
-    ESC [ 33 m      # yellow
-    ESC [ 34 m      # blue
-    ESC [ 35 m      # magenta
-    ESC [ 36 m      # cyan
-    ESC [ 37 m      # white
-    ESC [ 39 m      # reset
-
-    # BACKGROUND
-    ESC [ 40 m      # black
-    ESC [ 41 m      # red
-    ESC [ 42 m      # green
-    ESC [ 43 m      # yellow
-    ESC [ 44 m      # blue
-    ESC [ 45 m      # magenta
-    ESC [ 46 m      # cyan
-    ESC [ 47 m      # white
-    ESC [ 49 m      # reset
-
-    # cursor positioning
-    ESC [ y;x H     # position cursor at x across, y down
-
-    # clear the screen
-    ESC [ mode J    # clear the screen. Only mode 2 (clear entire screen)
-                    # is supported. It should be easy to add other modes,
-                    # let me know if that would be useful.
-
-Multiple numeric params to the 'm' command can be combined into a single
-sequence, eg::
-
-    ESC [ 36 ; 45 ; 1 m     # bright cyan text on magenta background
-
-All other ANSI sequences of the form ``ESC [ <param> ; <param> ... <command>``
-are silently stripped from the output on Windows.
-
-Any other form of ANSI sequence, such as single-character codes or alternative
-initial characters, are not recognised nor stripped. It would be cool to add
-them though. Let me know if it would be useful for you, via the issues on
-google code.
-
-
-Development
-===========
-
-Help and fixes welcome! Ask Jonathan for commit rights, you'll get them.
-
-Running tests requires:
-
-- Michael Foord's 'mock' module to be installed.
-- Tests are written using the 2010 era updates to 'unittest', and require to
-  be run either using Python2.7 or greater, or else to have Michael Foord's
-  'unittest2' module installed.
-
-unittest2 test discovery doesn't work for colorama, so I use 'nose'::
-
-    nosetests -s
-
-The -s is required because 'nosetests' otherwise applies a proxy of its own to
-stdout, which confuses the unit tests.
-
-
-Contact
-=======
-
-Created by Jonathan Hartley, tartley@tartley.com
-
-
-Thanks
-======
-| Ben Hoyt, for a magnificent fix under 64-bit Windows.
-| Jesse@EmptySquare for submitting a fix for examples in the README.
-| User 'jamessp', an observant documentation fix for cursor positioning.
-| User 'vaal1239', Dave Mckee & Lackner Kristof for a tiny but much-needed Win7 fix.
-| Julien Stuyck, for wisely suggesting Python3 compatible updates to README.
-| Daniel Griffith for multiple fabulous patches.
-| Oscar Lesta for valuable fix to stop ANSI chars being sent to non-tty output.
-| Roger Binns, for many suggestions, valuable feedback, & bug reports.
-| Tim Golden for thought and much appreciated feedback on the initial idea.
-
diff --git a/third_party/colorama/__init__.py b/third_party/colorama/__init__.py
index 2d127fa..2a3bf47 100644
--- a/third_party/colorama/__init__.py
+++ b/third_party/colorama/__init__.py
@@ -1,7 +1,6 @@
 # Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file.
-from .initialise import init, deinit, reinit
-from .ansi import Fore, Back, Style
+from .initialise import init, deinit, reinit, colorama_text
+from .ansi import Fore, Back, Style, Cursor
 from .ansitowin32 import AnsiToWin32
 
-VERSION = '0.2.7'
-
+__version__ = '0.4.1'
diff --git a/third_party/colorama/ansi.py b/third_party/colorama/ansi.py
index 5dfe374..7877658 100644
--- a/third_party/colorama/ansi.py
+++ b/third_party/colorama/ansi.py
@@ -5,46 +5,98 @@
 '''
 
 CSI = '\033['
+OSC = '\033]'
+BEL = '\007'
+
 
 def code_to_chars(code):
     return CSI + str(code) + 'm'
 
+def set_title(title):
+    return OSC + '2;' + title + BEL
+
+def clear_screen(mode=2):
+    return CSI + str(mode) + 'J'
+
+def clear_line(mode=2):
+    return CSI + str(mode) + 'K'
+
+
 class AnsiCodes(object):
-    def __init__(self, codes):
-        for name in dir(codes):
+    def __init__(self):
+        # the subclasses declare class attributes which are numbers.
+        # Upon instantiation we define instance attributes, which are the same
+        # as the class attributes but wrapped with the ANSI escape sequence
+        for name in dir(self):
             if not name.startswith('_'):
-                value = getattr(codes, name)
+                value = getattr(self, name)
                 setattr(self, name, code_to_chars(value))
 
-class AnsiFore:
-    BLACK   = 30
-    RED     = 31
-    GREEN   = 32
-    YELLOW  = 33
-    BLUE    = 34
-    MAGENTA = 35
-    CYAN    = 36
-    WHITE   = 37
-    RESET   = 39
 
-class AnsiBack:
-    BLACK   = 40
-    RED     = 41
-    GREEN   = 42
-    YELLOW  = 43
-    BLUE    = 44
-    MAGENTA = 45
-    CYAN    = 46
-    WHITE   = 47
-    RESET   = 49
+class AnsiCursor(object):
+    def UP(self, n=1):
+        return CSI + str(n) + 'A'
+    def DOWN(self, n=1):
+        return CSI + str(n) + 'B'
+    def FORWARD(self, n=1):
+        return CSI + str(n) + 'C'
+    def BACK(self, n=1):
+        return CSI + str(n) + 'D'
+    def POS(self, x=1, y=1):
+        return CSI + str(y) + ';' + str(x) + 'H'
 
-class AnsiStyle:
+
+class AnsiFore(AnsiCodes):
+    BLACK           = 30
+    RED             = 31
+    GREEN           = 32
+    YELLOW          = 33
+    BLUE            = 34
+    MAGENTA         = 35
+    CYAN            = 36
+    WHITE           = 37
+    RESET           = 39
+
+    # These are fairly well supported, but not part of the standard.
+    LIGHTBLACK_EX   = 90
+    LIGHTRED_EX     = 91
+    LIGHTGREEN_EX   = 92
+    LIGHTYELLOW_EX  = 93
+    LIGHTBLUE_EX    = 94
+    LIGHTMAGENTA_EX = 95
+    LIGHTCYAN_EX    = 96
+    LIGHTWHITE_EX   = 97
+
+
+class AnsiBack(AnsiCodes):
+    BLACK           = 40
+    RED             = 41
+    GREEN           = 42
+    YELLOW          = 43
+    BLUE            = 44
+    MAGENTA         = 45
+    CYAN            = 46
+    WHITE           = 47
+    RESET           = 49
+
+    # These are fairly well supported, but not part of the standard.
+    LIGHTBLACK_EX   = 100
+    LIGHTRED_EX     = 101
+    LIGHTGREEN_EX   = 102
+    LIGHTYELLOW_EX  = 103
+    LIGHTBLUE_EX    = 104
+    LIGHTMAGENTA_EX = 105
+    LIGHTCYAN_EX    = 106
+    LIGHTWHITE_EX   = 107
+
+
+class AnsiStyle(AnsiCodes):
     BRIGHT    = 1
     DIM       = 2
     NORMAL    = 22
     RESET_ALL = 0
 
-Fore = AnsiCodes( AnsiFore )
-Back = AnsiCodes( AnsiBack )
-Style = AnsiCodes( AnsiStyle )
-
+Fore   = AnsiFore()
+Back   = AnsiBack()
+Style  = AnsiStyle()
+Cursor = AnsiCursor()
diff --git a/third_party/colorama/ansitowin32.py b/third_party/colorama/ansitowin32.py
index ea0a6c1..359c92b 100644
--- a/third_party/colorama/ansitowin32.py
+++ b/third_party/colorama/ansitowin32.py
@@ -1,20 +1,18 @@
 # Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file.
 import re
 import sys
+import os
 
 from .ansi import AnsiFore, AnsiBack, AnsiStyle, Style
 from .winterm import WinTerm, WinColor, WinStyle
-from .win32 import windll
+from .win32 import windll, winapi_test
 
 
+winterm = None
 if windll is not None:
     winterm = WinTerm()
 
 
-def is_a_tty(stream):
-    return hasattr(stream, 'isatty') and stream.isatty()
-
-
 class StreamWrapper(object):
     '''
     Wraps a stream (such as stdout), acting as a transparent proxy for all
@@ -30,9 +28,38 @@
     def __getattr__(self, name):
         return getattr(self.__wrapped, name)
 
+    def __enter__(self, *args, **kwargs):
+        # special method lookup bypasses __getattr__/__getattribute__, see
+        # https://stackoverflow.com/questions/12632894/why-doesnt-getattr-work-with-exit
+        # thus, contextlib magic methods are not proxied via __getattr__
+        return self.__wrapped.__enter__(*args, **kwargs)
+
+    def __exit__(self, *args, **kwargs):
+        return self.__wrapped.__exit__(*args, **kwargs)
+
     def write(self, text):
         self.__convertor.write(text)
 
+    def isatty(self):
+        stream = self.__wrapped
+        if 'PYCHARM_HOSTED' in os.environ:
+            if stream is not None and (stream is sys.__stdout__ or stream is sys.__stderr__):
+                return True
+        try:
+            stream_isatty = stream.isatty
+        except AttributeError:
+            return False
+        else:
+            return stream_isatty()
+
+    @property
+    def closed(self):
+        stream = self.__wrapped
+        try:
+            return stream.closed
+        except AttributeError:
+            return True
+
 
 class AnsiToWin32(object):
     '''
@@ -40,7 +67,8 @@
     sequences from the text, and if outputting to a tty, will convert them into
     win32 function calls.
     '''
-    ANSI_RE = re.compile('\033\[((?:\d|;)*)([a-zA-Z])')
+    ANSI_CSI_RE = re.compile('\001?\033\\[((?:\\d|;)*)([a-zA-Z])\002?')   # Control Sequence Introducer
+    ANSI_OSC_RE = re.compile('\001?\033\\]((?:.|;)*?)(\x07)\002?')        # Operating System Command
 
     def __init__(self, wrapped, convert=None, strip=None, autoreset=False):
         # The wrapped stream (normally sys.stdout or sys.stderr)
@@ -52,16 +80,21 @@
         # create the proxy wrapping our output stream
         self.stream = StreamWrapper(wrapped, self)
 
-        on_windows = sys.platform.startswith('win')
+        on_windows = os.name == 'nt'
+        # We test if the WinAPI works, because even if we are on Windows
+        # we may be using a terminal that doesn't support the WinAPI
+        # (e.g. Cygwin Terminal). In this case it's up to the terminal
+        # to support the ANSI codes.
+        conversion_supported = on_windows and winapi_test()
 
         # should we strip ANSI sequences from our output?
         if strip is None:
-            strip = on_windows
+            strip = conversion_supported or (not self.stream.closed and not self.stream.isatty())
         self.strip = strip
 
         # should we should convert ANSI sequences into win32 calls?
         if convert is None:
-            convert = on_windows and is_a_tty(wrapped)
+            convert = conversion_supported and not self.stream.closed and self.stream.isatty()
         self.convert = convert
 
         # dict of ansi codes to win32 functions and parameters
@@ -70,7 +103,6 @@
         # are we wrapping stderr?
         self.on_stderr = self.wrapped is sys.stderr
 
-
     def should_wrap(self):
         '''
         True if this class is actually needed. If false, then the output
@@ -81,7 +113,6 @@
         '''
         return self.convert or self.strip or self.autoreset
 
-
     def get_win32_calls(self):
         if self.convert and winterm:
             return {
@@ -98,6 +129,14 @@
                 AnsiFore.CYAN: (winterm.fore, WinColor.CYAN),
                 AnsiFore.WHITE: (winterm.fore, WinColor.GREY),
                 AnsiFore.RESET: (winterm.fore, ),
+                AnsiFore.LIGHTBLACK_EX: (winterm.fore, WinColor.BLACK, True),
+                AnsiFore.LIGHTRED_EX: (winterm.fore, WinColor.RED, True),
+                AnsiFore.LIGHTGREEN_EX: (winterm.fore, WinColor.GREEN, True),
+                AnsiFore.LIGHTYELLOW_EX: (winterm.fore, WinColor.YELLOW, True),
+                AnsiFore.LIGHTBLUE_EX: (winterm.fore, WinColor.BLUE, True),
+                AnsiFore.LIGHTMAGENTA_EX: (winterm.fore, WinColor.MAGENTA, True),
+                AnsiFore.LIGHTCYAN_EX: (winterm.fore, WinColor.CYAN, True),
+                AnsiFore.LIGHTWHITE_EX: (winterm.fore, WinColor.GREY, True),
                 AnsiBack.BLACK: (winterm.back, WinColor.BLACK),
                 AnsiBack.RED: (winterm.back, WinColor.RED),
                 AnsiBack.GREEN: (winterm.back, WinColor.GREEN),
@@ -107,8 +146,16 @@
                 AnsiBack.CYAN: (winterm.back, WinColor.CYAN),
                 AnsiBack.WHITE: (winterm.back, WinColor.GREY),
                 AnsiBack.RESET: (winterm.back, ),
+                AnsiBack.LIGHTBLACK_EX: (winterm.back, WinColor.BLACK, True),
+                AnsiBack.LIGHTRED_EX: (winterm.back, WinColor.RED, True),
+                AnsiBack.LIGHTGREEN_EX: (winterm.back, WinColor.GREEN, True),
+                AnsiBack.LIGHTYELLOW_EX: (winterm.back, WinColor.YELLOW, True),
+                AnsiBack.LIGHTBLUE_EX: (winterm.back, WinColor.BLUE, True),
+                AnsiBack.LIGHTMAGENTA_EX: (winterm.back, WinColor.MAGENTA, True),
+                AnsiBack.LIGHTCYAN_EX: (winterm.back, WinColor.CYAN, True),
+                AnsiBack.LIGHTWHITE_EX: (winterm.back, WinColor.GREY, True),
             }
-
+        return dict()
 
     def write(self, text):
         if self.strip or self.convert:
@@ -123,7 +170,7 @@
     def reset_all(self):
         if self.convert:
             self.call_win32('m', (0,))
-        elif is_a_tty(self.wrapped):
+        elif not self.strip and not self.stream.closed:
             self.wrapped.write(Style.RESET_ALL)
 
 
@@ -134,7 +181,8 @@
         calls.
         '''
         cursor = 0
-        for match in self.ANSI_RE.finditer(text):
+        text = self.convert_osc(text)
+        for match in self.ANSI_CSI_RE.finditer(text):
             start, end = match.span()
             self.write_plain_text(text, cursor, start)
             self.convert_ansi(*match.groups())
@@ -150,21 +198,29 @@
 
     def convert_ansi(self, paramstring, command):
         if self.convert:
-            params = self.extract_params(paramstring)
+            params = self.extract_params(command, paramstring)
             self.call_win32(command, params)
 
 
-    def extract_params(self, paramstring):
-        def split(paramstring):
-            for p in paramstring.split(';'):
-                if p != '':
-                    yield int(p)
-        return tuple(split(paramstring))
+    def extract_params(self, command, paramstring):
+        if command in 'Hf':
+            params = tuple(int(p) if len(p) != 0 else 1 for p in paramstring.split(';'))
+            while len(params) < 2:
+                # defaults:
+                params = params + (1,)
+        else:
+            params = tuple(int(p) for p in paramstring.split(';') if len(p) != 0)
+            if len(params) == 0:
+                # defaults:
+                if command in 'JKm':
+                    params = (0,)
+                elif command in 'ABCD':
+                    params = (1,)
+
+        return params
 
 
     def call_win32(self, command, params):
-        if params == []:
-            params = [0]
         if command == 'm':
             for param in params:
                 if param in self.win32_calls:
@@ -173,17 +229,29 @@
                     args = func_args[1:]
                     kwargs = dict(on_stderr=self.on_stderr)
                     func(*args, **kwargs)
-        elif command in ('H', 'f'): # set cursor position
-            func = winterm.set_cursor_position
-            func(params, on_stderr=self.on_stderr)
-        elif command in ('J'):
-            func = winterm.erase_data
-            func(params, on_stderr=self.on_stderr)
-        elif command == 'A':
-            if params == () or params == None:
-                num_rows = 1
-            else:
-                num_rows = params[0]
-            func = winterm.cursor_up
-            func(num_rows, on_stderr=self.on_stderr)
+        elif command in 'J':
+            winterm.erase_screen(params[0], on_stderr=self.on_stderr)
+        elif command in 'K':
+            winterm.erase_line(params[0], on_stderr=self.on_stderr)
+        elif command in 'Hf':     # cursor position - absolute
+            winterm.set_cursor_position(params, on_stderr=self.on_stderr)
+        elif command in 'ABCD':   # cursor position - relative
+            n = params[0]
+            # A - up, B - down, C - forward, D - back
+            x, y = {'A': (0, -n), 'B': (0, n), 'C': (n, 0), 'D': (-n, 0)}[command]
+            winterm.cursor_adjust(x, y, on_stderr=self.on_stderr)
 
+
+    def convert_osc(self, text):
+        for match in self.ANSI_OSC_RE.finditer(text):
+            start, end = match.span()
+            text = text[:start] + text[end:]
+            paramstring, command = match.groups()
+            if command in '\x07':       # \x07 = BEL
+                params = paramstring.split(";")
+                # 0 - change title and icon (we will only change title)
+                # 1 - change icon (we don't support this)
+                # 2 - change title
+                if params[0] in '02':
+                    winterm.set_title(params[1])
+        return text
diff --git a/third_party/colorama/initialise.py b/third_party/colorama/initialise.py
index cba3676..430d066 100644
--- a/third_party/colorama/initialise.py
+++ b/third_party/colorama/initialise.py
@@ -1,21 +1,23 @@
 # Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file.
 import atexit
+import contextlib
 import sys
 
 from .ansitowin32 import AnsiToWin32
 
 
-orig_stdout = sys.stdout
-orig_stderr = sys.stderr
+orig_stdout = None
+orig_stderr = None
 
-wrapped_stdout = sys.stdout
-wrapped_stderr = sys.stderr
+wrapped_stdout = None
+wrapped_stderr = None
 
 atexit_done = False
 
 
 def reset_all():
-    AnsiToWin32(orig_stdout).reset_all()
+    if AnsiToWin32 is not None:    # Issue #74: objects might become None at exit
+        AnsiToWin32(orig_stdout).reset_all()
 
 
 def init(autoreset=False, convert=None, strip=None, wrap=True):
@@ -24,10 +26,21 @@
         raise ValueError('wrap=False conflicts with any other arg=True')
 
     global wrapped_stdout, wrapped_stderr
-    sys.stdout = wrapped_stdout = \
-        wrap_stream(orig_stdout, convert, strip, autoreset, wrap)
-    sys.stderr = wrapped_stderr = \
-        wrap_stream(orig_stderr, convert, strip, autoreset, wrap)
+    global orig_stdout, orig_stderr
+
+    orig_stdout = sys.stdout
+    orig_stderr = sys.stderr
+
+    if sys.stdout is None:
+        wrapped_stdout = None
+    else:
+        sys.stdout = wrapped_stdout = \
+            wrap_stream(orig_stdout, convert, strip, autoreset, wrap)
+    if sys.stderr is None:
+        wrapped_stderr = None
+    else:
+        sys.stderr = wrapped_stderr = \
+            wrap_stream(orig_stderr, convert, strip, autoreset, wrap)
 
     global atexit_done
     if not atexit_done:
@@ -36,13 +49,26 @@
 
 
 def deinit():
-    sys.stdout = orig_stdout
-    sys.stderr = orig_stderr
+    if orig_stdout is not None:
+        sys.stdout = orig_stdout
+    if orig_stderr is not None:
+        sys.stderr = orig_stderr
+
+
+@contextlib.contextmanager
+def colorama_text(*args, **kwargs):
+    init(*args, **kwargs)
+    try:
+        yield
+    finally:
+        deinit()
 
 
 def reinit():
-    sys.stdout = wrapped_stdout
-    sys.stderr = wrapped_stdout
+    if wrapped_stdout is not None:
+        sys.stdout = wrapped_stdout
+    if wrapped_stderr is not None:
+        sys.stderr = wrapped_stderr
 
 
 def wrap_stream(stream, convert, strip, autoreset, wrap):
@@ -52,5 +78,3 @@
         if wrapper.should_wrap():
             stream = wrapper.stream
     return stream
-
-
diff --git a/third_party/colorama/win32.py b/third_party/colorama/win32.py
index f4024f9..c2d8360 100644
--- a/third_party/colorama/win32.py
+++ b/third_party/colorama/win32.py
@@ -5,24 +5,27 @@
 STDERR = -12
 
 try:
-    from ctypes import windll
+    import ctypes
+    from ctypes import LibraryLoader
+    windll = LibraryLoader(ctypes.WinDLL)
     from ctypes import wintypes
-except ImportError:
+except (AttributeError, ImportError):
     windll = None
     SetConsoleTextAttribute = lambda *_: None
+    winapi_test = lambda *_: None
 else:
-    from ctypes import (
-        byref, Structure, c_char, c_short, c_uint32, c_ushort, POINTER
-    )
+    from ctypes import byref, Structure, c_char, POINTER
+
+    COORD = wintypes._COORD
 
     class CONSOLE_SCREEN_BUFFER_INFO(Structure):
         """struct in wincon.h."""
         _fields_ = [
-            ("dwSize", wintypes._COORD),
-            ("dwCursorPosition", wintypes._COORD),
+            ("dwSize", COORD),
+            ("dwCursorPosition", COORD),
             ("wAttributes", wintypes.WORD),
             ("srWindow", wintypes.SMALL_RECT),
-            ("dwMaximumWindowSize", wintypes._COORD),
+            ("dwMaximumWindowSize", COORD),
         ]
         def __str__(self):
             return '(%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d)' % (
@@ -56,7 +59,7 @@
     _SetConsoleCursorPosition = windll.kernel32.SetConsoleCursorPosition
     _SetConsoleCursorPosition.argtypes = [
         wintypes.HANDLE,
-        wintypes._COORD,
+        COORD,
     ]
     _SetConsoleCursorPosition.restype = wintypes.BOOL
 
@@ -65,7 +68,7 @@
         wintypes.HANDLE,
         c_char,
         wintypes.DWORD,
-        wintypes._COORD,
+        COORD,
         POINTER(wintypes.DWORD),
     ]
     _FillConsoleOutputCharacterA.restype = wintypes.BOOL
@@ -75,47 +78,59 @@
         wintypes.HANDLE,
         wintypes.WORD,
         wintypes.DWORD,
-        wintypes._COORD,
+        COORD,
         POINTER(wintypes.DWORD),
     ]
     _FillConsoleOutputAttribute.restype = wintypes.BOOL
 
-    handles = {
-        STDOUT: _GetStdHandle(STDOUT),
-        STDERR: _GetStdHandle(STDERR),
-    }
+    _SetConsoleTitleW = windll.kernel32.SetConsoleTitleW
+    _SetConsoleTitleW.argtypes = [
+        wintypes.LPCWSTR
+    ]
+    _SetConsoleTitleW.restype = wintypes.BOOL
+
+    def _winapi_test(handle):
+        csbi = CONSOLE_SCREEN_BUFFER_INFO()
+        success = _GetConsoleScreenBufferInfo(
+            handle, byref(csbi))
+        return bool(success)
+
+    def winapi_test():
+        return any(_winapi_test(h) for h in
+                   (_GetStdHandle(STDOUT), _GetStdHandle(STDERR)))
 
     def GetConsoleScreenBufferInfo(stream_id=STDOUT):
-        handle = handles[stream_id]
+        handle = _GetStdHandle(stream_id)
         csbi = CONSOLE_SCREEN_BUFFER_INFO()
         success = _GetConsoleScreenBufferInfo(
             handle, byref(csbi))
         return csbi
 
     def SetConsoleTextAttribute(stream_id, attrs):
-        handle = handles[stream_id]
+        handle = _GetStdHandle(stream_id)
         return _SetConsoleTextAttribute(handle, attrs)
 
-    def SetConsoleCursorPosition(stream_id, position):
-        position = wintypes._COORD(*position)
+    def SetConsoleCursorPosition(stream_id, position, adjust=True):
+        position = COORD(*position)
         # If the position is out of range, do nothing.
         if position.Y <= 0 or position.X <= 0:
             return
         # Adjust for Windows' SetConsoleCursorPosition:
         #    1. being 0-based, while ANSI is 1-based.
         #    2. expecting (x,y), while ANSI uses (y,x).
-        adjusted_position = wintypes._COORD(position.Y - 1, position.X - 1)
-        # Adjust for viewport's scroll position
-        sr = GetConsoleScreenBufferInfo(STDOUT).srWindow
-        adjusted_position.Y += sr.Top
-        adjusted_position.X += sr.Left
+        adjusted_position = COORD(position.Y - 1, position.X - 1)
+        if adjust:
+            # Adjust for viewport's scroll position
+            sr = GetConsoleScreenBufferInfo(STDOUT).srWindow
+            adjusted_position.Y += sr.Top
+            adjusted_position.X += sr.Left
         # Resume normal processing
-        handle = handles[stream_id]
+        handle = _GetStdHandle(stream_id)
         return _SetConsoleCursorPosition(handle, adjusted_position)
 
     def FillConsoleOutputCharacter(stream_id, char, length, start):
-        handle = handles[stream_id]
-        char = c_char(char)
+        handle = _GetStdHandle(stream_id)
+        char = c_char(char.encode())
         length = wintypes.DWORD(length)
         num_written = wintypes.DWORD(0)
         # Note that this is hard-coded for ANSI (vs wide) bytes.
@@ -125,10 +140,13 @@
 
     def FillConsoleOutputAttribute(stream_id, attr, length, start):
         ''' FillConsoleOutputAttribute( hConsole, csbi.wAttributes, dwConSize, coordScreen, &cCharsWritten )'''
-        handle = handles[stream_id]
+        handle = _GetStdHandle(stream_id)
         attribute = wintypes.WORD(attr)
         length = wintypes.DWORD(length)
         num_written = wintypes.DWORD(0)
         # Note that this is hard-coded for ANSI (vs wide) bytes.
         return _FillConsoleOutputAttribute(
             handle, attribute, length, start, byref(num_written))
+
+    def SetConsoleTitle(title):
+        return _SetConsoleTitleW(title)
diff --git a/third_party/colorama/winterm.py b/third_party/colorama/winterm.py
index 2708811..0fdb4ec 100644
--- a/third_party/colorama/winterm.py
+++ b/third_party/colorama/winterm.py
@@ -15,9 +15,9 @@
 
 # from wincon.h
 class WinStyle(object):
-    NORMAL = 0x00 # dim text, dim background
-    BRIGHT = 0x08 # bright text, dim background
-
+    NORMAL              = 0x00 # dim text, dim background
+    BRIGHT              = 0x08 # bright text, dim background
+    BRIGHT_BACKGROUND   = 0x80 # dim text, bright background
 
 class WinTerm(object):
 
@@ -27,29 +27,45 @@
         self._default_fore = self._fore
         self._default_back = self._back
         self._default_style = self._style
+        # In order to emulate LIGHT_EX in windows, we borrow the BRIGHT style.
+        # So that LIGHT_EX colors and BRIGHT style do not clobber each other,
+        # we track them separately, since LIGHT_EX is overwritten by Fore/Back
+        # and BRIGHT is overwritten by Style codes.
+        self._light = 0
 
     def get_attrs(self):
-        return self._fore + self._back * 16 + self._style
+        return self._fore + self._back * 16 + (self._style | self._light)
 
     def set_attrs(self, value):
         self._fore = value & 7
         self._back = (value >> 4) & 7
-        self._style = value & WinStyle.BRIGHT
+        self._style = value & (WinStyle.BRIGHT | WinStyle.BRIGHT_BACKGROUND)
 
     def reset_all(self, on_stderr=None):
         self.set_attrs(self._default)
         self.set_console(attrs=self._default)
+        self._light = 0
 
-    def fore(self, fore=None, on_stderr=False):
+    def fore(self, fore=None, light=False, on_stderr=False):
         if fore is None:
             fore = self._default_fore
         self._fore = fore
+        # Emulate LIGHT_EX with BRIGHT Style
+        if light:
+            self._light |= WinStyle.BRIGHT
+        else:
+            self._light &= ~WinStyle.BRIGHT
         self.set_console(on_stderr=on_stderr)
 
-    def back(self, back=None, on_stderr=False):
+    def back(self, back=None, light=False, on_stderr=False):
         if back is None:
             back = self._default_back
         self._back = back
+        # Emulate LIGHT_EX with BRIGHT_BACKGROUND Style
+        if light:
+            self._light |= WinStyle.BRIGHT_BACKGROUND
+        else:
+            self._light &= ~WinStyle.BRIGHT_BACKGROUND
         self.set_console(on_stderr=on_stderr)
 
     def style(self, style=None, on_stderr=False):
@@ -73,48 +89,81 @@
         position.X += 1
         position.Y += 1
         return position
-    
+
     def set_cursor_position(self, position=None, on_stderr=False):
         if position is None:
-            #I'm not currently tracking the position, so there is no default.
-            #position = self.get_position()
+            # I'm not currently tracking the position, so there is no default.
+            # position = self.get_position()
             return
         handle = win32.STDOUT
         if on_stderr:
             handle = win32.STDERR
         win32.SetConsoleCursorPosition(handle, position)
 
-    def cursor_up(self, num_rows=0, on_stderr=False):
-        if num_rows == 0:
-            return
+    def cursor_adjust(self, x, y, on_stderr=False):
         handle = win32.STDOUT
         if on_stderr:
             handle = win32.STDERR
         position = self.get_position(handle)
-        adjusted_position = (position.Y - num_rows, position.X)
-        self.set_cursor_position(adjusted_position, on_stderr)
+        adjusted_position = (position.Y + y, position.X + x)
+        win32.SetConsoleCursorPosition(handle, adjusted_position, adjust=False)
 
-    def erase_data(self, mode=0, on_stderr=False):
-        # 0 (or None) should clear from the cursor to the end of the screen.
+    def erase_screen(self, mode=0, on_stderr=False):
+        # 0 should clear from the cursor to the end of the screen.
         # 1 should clear from the cursor to the beginning of the screen.
-        # 2 should clear the entire screen. (And maybe move cursor to (1,1)?)
-        #
-        # At the moment, I only support mode 2. From looking at the API, it
-        #    should be possible to calculate a different number of bytes to clear,
-        #    and to do so relative to the cursor position.
-        if mode[0] not in (2,):
-            return
+        # 2 should clear the entire screen, and move cursor to (1,1)
         handle = win32.STDOUT
         if on_stderr:
             handle = win32.STDERR
-        # here's where we'll home the cursor
-        coord_screen = win32.COORD(0,0)
         csbi = win32.GetConsoleScreenBufferInfo(handle)
         # get the number of character cells in the current buffer
-        dw_con_size = csbi.dwSize.X * csbi.dwSize.Y
+        cells_in_screen = csbi.dwSize.X * csbi.dwSize.Y
+        # get number of character cells before current cursor position
+        cells_before_cursor = csbi.dwSize.X * csbi.dwCursorPosition.Y + csbi.dwCursorPosition.X
+        if mode == 0:
+            from_coord = csbi.dwCursorPosition
+            cells_to_erase = cells_in_screen - cells_before_cursor
+        elif mode == 1:
+            from_coord = win32.COORD(0, 0)
+            cells_to_erase = cells_before_cursor
+        elif mode == 2:
+            from_coord = win32.COORD(0, 0)
+            cells_to_erase = cells_in_screen
+        else:
+            # invalid mode
+            return
         # fill the entire screen with blanks
-        win32.FillConsoleOutputCharacter(handle, ' ', dw_con_size, coord_screen)
+        win32.FillConsoleOutputCharacter(handle, ' ', cells_to_erase, from_coord)
         # now set the buffer's attributes accordingly
-        win32.FillConsoleOutputAttribute(handle, self.get_attrs(), dw_con_size, coord_screen );
-        # put the cursor at (0, 0)
-        win32.SetConsoleCursorPosition(handle, (coord_screen.X, coord_screen.Y))
+        win32.FillConsoleOutputAttribute(handle, self.get_attrs(), cells_to_erase, from_coord)
+        if mode == 2:
+            # put the cursor where needed
+            win32.SetConsoleCursorPosition(handle, (1, 1))
+
+    def erase_line(self, mode=0, on_stderr=False):
+        # 0 should clear from the cursor to the end of the line.
+        # 1 should clear from the cursor to the beginning of the line.
+        # 2 should clear the entire line.
+        handle = win32.STDOUT
+        if on_stderr:
+            handle = win32.STDERR
+        csbi = win32.GetConsoleScreenBufferInfo(handle)
+        if mode == 0:
+            from_coord = csbi.dwCursorPosition
+            cells_to_erase = csbi.dwSize.X - csbi.dwCursorPosition.X
+        elif mode == 1:
+            from_coord = win32.COORD(0, csbi.dwCursorPosition.Y)
+            cells_to_erase = csbi.dwCursorPosition.X
+        elif mode == 2:
+            from_coord = win32.COORD(0, csbi.dwCursorPosition.Y)
+            cells_to_erase = csbi.dwSize.X
+        else:
+            # invalid mode
+            return
+        # fill the entire screen with blanks
+        win32.FillConsoleOutputCharacter(handle, ' ', cells_to_erase, from_coord)
+        # now set the buffer's attributes accordingly
+        win32.FillConsoleOutputAttribute(handle, self.get_attrs(), cells_to_erase, from_coord)
+
+    def set_title(self, title):
+        win32.SetConsoleTitle(title)