From 35f13db15dcde21d5392fbcdb09d07216702ab0e Mon Sep 17 00:00:00 2001
From: Andre Anjos <andre.dos.anjos@gmail.com>
Date: Thu, 14 Feb 2019 09:23:08 +0100
Subject: [PATCH] [package] Add color support

---
 bob/devtools/log.py | 87 ++++++++++++++++++++++++++++++++++++++++++++-
 conda/meta.yaml     |  1 +
 setup.py            |  1 +
 3 files changed, 88 insertions(+), 1 deletion(-)

diff --git a/bob/devtools/log.py b/bob/devtools/log.py
index 3cc7c783..50842dc7 100644
--- a/bob/devtools/log.py
+++ b/bob/devtools/log.py
@@ -7,6 +7,10 @@
 import sys
 import logging
 
+import click
+import termcolor
+
+
 # get the default root logger of Bob
 _logger = logging.getLogger('bob')
 
@@ -28,6 +32,87 @@ _debug_info.addFilter(_InfoFilter())
 _logger.addHandler(_debug_info)
 
 
+COLORMAP = dict(
+    debug=dict(),
+    info=dict(attrs=['bold']),
+    warn=dict(color='yellow', attrs=['bold']),
+    warning=dict(color='yellow', attrs=['bold']),
+    error=dict(color='red'),
+    exception=dict(color='red', attrs=['bold']),
+    critical=dict(color='red', attrs=['bold']),
+    )
+'''Default color map for homogenized color display'''
+
+
+def _supports_color():
+  """
+  Returns True if the running system's terminal supports color, and False
+  otherwise.
+  """
+  plat = sys.platform
+  supported_platform = plat != 'Pocket PC' and (plat != 'win32' or
+                                                'ANSICON' in os.environ)
+  # isatty is not always implemented, #6223.
+  is_a_tty = hasattr(sys.stdout, 'isatty') and sys.stdout.isatty()
+  if not supported_platform or not is_a_tty:
+    return False
+  return True
+
+
+class ColorLog(object):
+  '''Colorizes logging colors'''
+
+  def __init__(self, logger):
+    self._log = logger
+
+  def __getattr__(self, name):
+    if name in ['debug', 'info', 'warn', 'warning', 'error', 'exception',
+        'critical']:
+      if _supports_color():
+        return lambda s, *args: getattr(self._log, name)(
+            termcolor.colored(s, **COLORMAP[name]), *args)
+      else:
+        return lambda s, *args: getattr(self._log, name)(s, *args)
+
+    return getattr(self._log, name)
+
+
+def get_logger(name):
+  """Returns the default logger as setup by this module"""
+
+  return ColorLog(logging.getLogger(name))
+
+
+def _echo(text, *args, **kwargs):
+  """Provides a colorized version of :py:func:`click.echo` (for terminals)
+
+  The color is stripped off if outputting to a file or piping the results of
+  a command using this function.
+
+  Parameters:
+
+    text (str): The text to be printed
+    args (tuple): Tuple of attributes directly passed to
+      :py:func:`termcolor.colored`
+    kwargs (dict): Dictionary of attributes directly passed to
+      :py:func:`termcolor.colored`
+  """
+
+  click.echo(termcolor.colored(text, *args, **kwargs))
+
+
+def echo_normal(text):
+  """Color preset for normal text output for :py:func:`click.echo`"""
+
+  _echo(text, 'green')
+
+
+def echo_warning(text):
+  """Color preset for normal warning output for :py:func:`click.echo`"""
+
+  _echo(text, **COLORMAP['warn'])
+
+
 # helper functions to instantiate and set-up logging
 def setup(logger_name,
     format="%(levelname)s:%(name)s@%(asctime)s: %(message)s"):
@@ -68,7 +153,7 @@ def setup(logger_name,
   for handler in _logger.handlers:
     handler.setFormatter(formatter)
 
-  return logger
+  return ColorLog(logger)
 
 
 def set_verbosity_level(logger, level):
diff --git a/conda/meta.yaml b/conda/meta.yaml
index 09cd327e..79ea7417 100644
--- a/conda/meta.yaml
+++ b/conda/meta.yaml
@@ -47,6 +47,7 @@ requirements:
     - twine
     - lxml
     - jinja2
+    - termcolor
 
 test:
   requires:
diff --git a/setup.py b/setup.py
index d1e0f1ab..b37d0922 100644
--- a/setup.py
+++ b/setup.py
@@ -21,6 +21,7 @@ requires = [
     'twine',
     'lxml',
     'jinja2',
+    'termcolor',
     ]
 
 setup(
-- 
GitLab