Source code for plainbox.impl.color
# This file is part of Checkbox.
#
# Copyright 2013 Canonical Ltd.
# Written by:
# Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
#
# Checkbox is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 3,
# as published by the Free Software Foundation.
#
# Checkbox is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Checkbox. If not, see <http://www.gnu.org/licenses/>.
"""
:mod:`plainbox.impl.color` -- ANSI color codes
==============================================
"""
import sys
[docs]class ansi_on:
"""
ANSI control codes for various useful stuff.
Reference source: wikipedia
"""
[docs] class f:
"""
Foreground color attributes
"""
BLACK = 30
RED = 31
GREEN = 32
YELLOW = 33
BLUE = 34
MAGENTA = 35
CYAN = 36
WHITE = 37
# what was 38?
RESET = 39
[docs] class b:
"""
Background color attributes
"""
BLACK = 40
RED = 41
GREEN = 42
YELLOW = 44
BLUE = 44
MAGENTA = 45
CYAN = 46
WHITE = 47
# what was 48?
RESET = 49
for obj_on, obj_off in zip(
(ansi_on.f, ansi_on.b, ansi_on.s),
(ansi_off.f, ansi_off.b, ansi_off.s)):
for name in [name for name in dir(obj_on) if name.isupper()]:
setattr(obj_on, name, "\033[%sm" % getattr(obj_on, name))
setattr(obj_off, name, "")
# XXX: Temporary hack that disables colors on win32 until
# all of the codebase has been ported over to use colorama
if sys.platform == 'win32':
try:
import colorama
except ImportError:
ansi_on = ansi_off
else:
colorama.init()
[docs]def get_color_for_tty(stream=None):
"""
Get ``ansi_on`` if stdout is a tty, ``ansi_off`` otherwise.
:param stream:
Alternate stream to use (sys.stdout by default)
:returns:
``ansi_on`` or ``ansi_off``, depending on if the stream being a tty or
not.
"""
if stream is None:
stream = sys.stdout
return ansi_on if stream.isatty() else ansi_off
[docs]class Colorizer:
"""
Colorizing helper for various kinds of content we need to handle
"""
# NOTE: Ideally result and all would be handled by multi-dispatch __call__
def __init__(self, color=None):
if color is True:
self.c = ansi_on
elif color is False:
self.c = ansi_off
elif color is None:
self.c = get_color_for_tty()
else:
self.c = color
@property
def is_enabled(self):
"""
if true, this colorizer is actually using colors
This property is useful to let applications customize their
behavior if they know color support is desired and enabled.
"""
return self.c is ansi_on
[docs] def result(self, result):
return self.custom(
result.tr_outcome(), result.outcome_color_ansi())
[docs] def header(self, text, color_name='WHITE', bright=True, fill='='):
return self("[ {} ]".format(text).center(80, fill), color_name, bright)
def __call__(self, text, color_name="WHITE", bright=True):
return ''.join([
self.f(color_name),
self.c.s.BRIGHT if bright else '', str(text),
self.c.s.RESET_ALL])
[docs] def custom(self, text, ansi_code):
"""
Render a piece of text with custom ANSI styling sequence
:param text:
The text to stylize
:param ansi_code:
A string containing ANSI escape sequence to use.
:returns:
A combination of ``ansi_code``, ``text`` and a fixed
reset sequence that resets text styles.
.. note::
When the colorizer is not really doing anything (see
:meth:`is_enabled`) then custom text is not used at all. This is
done to ensure that any custom styling is not permantently enabled
if colors are to be disabled.
"""
return ''.join([
ansi_code if self.is_enabled else "",
text,
self.c.s.RESET_ALL])